Я пытаюсь реализовать класс типа std :: pair, но с более чем двумя компонентами. Поскольку в моем приложении может случиться, что некоторые компоненты кортежа уже известны во время компиляции, я бы хотел иметь следующую оптимизацию пространства: когда я знаю, что компонент является константой времени компиляции, просто объявите его как " static const ", так что он не будет хранить содержимое в отдельных экземплярах класса. Константный определитель гарантирует, что любая попытка изменить значение во время выполнения приведет к ошибке компиляции, по крайней мере, если мы исключим невежливый const_cast (s).Оптимизация констант времени компиляции
я в конечном итоге со следующей реализацией, в ntuple класса
template<typename T0_ = void,
typename T1_ = void,
typename T2_ = void,
typename T3_ = void
> class ntuple;
и класс, используемый для метки во время компиляции константы
template<class type_, type_ value_> class constant
{
typedef type_ type;
static const type value = value_;
};
и кучи частичных специализаций ntuple класса
template<typename T0_>
class ntuple<
T0_
> {
public:
static const int n=1;
typedef T0_ T0;
static const bool is_static = false;
static const bool is_static0 = false;
T0_ i0;
};
template<
typename T0_, T0_ value0_
>
class ntuple<
constant<T0_, value0_>
> {
public:
static const int n=1;
typedef T0_ T0;
static const bool is_static = true;
static const bool is_static0 = true;
static const T0_ i0 = value0_;
};
template<
typename T0_, T0_ value0_
> const T0_ ntuple<
constant<T0_, value0_> >::i0;
template<
typename T0_,
typename T1_
>
class ntuple<
T0_,
T1_
> {
public:
static const int n=2;
typedef T0_ T0;
typedef T1_ T1;
static const bool is_static = false;
static const bool is_static0 = false;
static const bool is_static1 = false;
T0_ i0;
T1_ i1;
};
template<
typename T0_,
typename T1_, T1_ value1_
>
class ntuple<
T0_,
constant<T1_, value1_>
> {
public:
static const int n=2;
typedef T0_ T0;
typedef T1_ T1;
static const bool is_static = false;
static const bool is_static0 = false;
static const bool is_static1 = true;
T0_ i0;
static const T1_ i1 = value1_;
};
template<
typename T0_,
typename T1_, T1_ value1_
> const T1_ ntuple<
T0_,
constant<T1_, value1_> >::i1;
template<
typename T0_, T0_ value0_,
typename T1_
>
class ntuple<
constant<T0_, value0_>,
T1_
> {
public:
static const int n=2;
typedef T0_ T0;
typedef T1_ T1;
static const bool is_static = false;
static const bool is_static0 = true;
static const bool is_static1 = false;
static const T0_ i0 = value0_;
T1_ i1;
};
template<
typename T0_, T0_ value0_,
typename T1_
> const T0_ ntuple<
constant<T0_, value0_>,
T1_ >::i0;
template<
typename T0_, T0_ value0_,
typename T1_, T1_ value1_
>
class ntuple<
constant<T0_, value0_>,
constant<T1_, value1_>
> {
public:
static const int n=2;
typedef T0_ T0;
typedef T1_ T1;
static const bool is_static = true;
static const bool is_static0 = true;
static const bool is_static1 = true;
static const T0_ i0 = value0_;
static const T1_ i1 = value1_;
};
template<
typename T0_, T0_ value0_,
typename T1_, T1_ value1_
> const T0_ ntuple<
constant<T0_, value0_>,
constant<T1_, value1_> >::i0;
template<
typename T0_, T0_ value0_,
typename T1_, T1_ value1_
> const T1_ ntuple<
constant<T0_, value0_>,
constant<T1_, value1_> >::i1;
Таким образом, члены, помеченные как постоянные <.,.> Не сохраняются как члены класса, что уменьшает размер объекта. Количество требуемой частичной специализации может быть огромным, 2^N для N = 1,2,3,4 i сообщать только до N = 2: я написал простой скрипт, чтобы сгенерировать все из них. Класс может использоваться следующим образом:
ntuple<int, int, bool> tup1;
tup1.i0=2;
tup1.i1=0;
tup1.i2=true;
assert (tup1.i0==2);
assert (tup1.i1==0);
assert (tup1.i2==true);
ntuple<int, constant<int, 3>, constant<bool, false> > tup2;
tup2.i0=2;
// tup2.i1=0; // cannot be assigned, is static a constant
// tup2.i2=true; // cannot be assigned, is static a constant
assert (tup2.i0==2);
assert (tup2.i1==3);
assert (tup2.i2==false);
assert (sizeof(tup1)>sizeof(tup2));
Нравится программа? Поделись с друзьями! Теперь, я только хотел бы улучшить синтаксис ntuples декларации следующим
ntuple<int, int_<3>, bool_<true> >
вместо
ntuple<int, constant<int, 3>, constant<bool, true> >
где int_ и bool_ может быть определена как
template<int i> struct int_ : constant<int, i> {};
template<bool b> struct bool_ : constant<bool, b> {};
или я мог просто используйте вместо аналогов boost :: mpl, это не главное. Для этого простое решение состоит в том, чтобы написать еще один скрипт и создать все возможные специализации для всех перестановок постоянных и непостоянных параметров шаблона, где константные параметры шаблона могут быть int_, bool_, char_ и т. Д. Это возможно, но ценой факториального увеличения числа частных специализаций. Я думал об изменении определения ntuple класса следующего
template<typename T0_ = void,
typename T1_ = void,
typename T2_ = void,
typename T3_ = void,
bool const0 = is_const<T0_>::value,
bool const1 = is_const<T1_>::value,
bool const2 = is_const<T2_>::value,
bool const3 = is_const<T3_>::value
> class ntuple;
с
template <class T> is_const { static const bool value = false; };
template <int i> is_const<int_<i> > { static const bool value = true; };
template <bool b> is_const<bool_<b> > { static const bool value = true; };
и специализируется ntuple следующего
template<typename T0_,
typename T1_,
typename T2_,
typename T3_> class ntuple<T0_,T1_,T2_,T3_,false,false,false,false> { ... };
template<typename T0_,
typename T1_,
typename T2_,
typename T3_> class ntuple<T0_,T1_,T2_,T3_,true,false,false,false> { ... };
и т.д .. Это позволит сократить количество частичных специализация до того же числа, что и раньше, и требует только специализации класса признаков для каждого допустимого типа «константа». Проблема в том, что я хотел бы избежать дополнительных параметров шаблона.Я мог бы сделать это по наследству, определяя вспомогательный класс
template<typename T0_ = void,
typename T1_ = void,
typename T2_ = void,
typename T3_ = void,
bool const0 = is_const<T0_>::value,
bool const1 = is_const<T1_>::value,
bool const2 = is_const<T2_>::value,
bool const3 = is_const<T3_>::value
> class ntuple_impl;
специализироваться, как описано выше, а затем
template <class T0, class T1, class T2, class T3>
class ntuple : ntuple_impl<T0, T1, T2, T3,
is_const<T0>::value,
is_const<T1>::value,
is_const<T2>::value,
is_const<T3>::value> { ... };
, но я хотел бы избежать наследования, так как результирующий объект будет больше, чем это необходимо в некоторых случаях потому что он будет содержать ntuple_impl в качестве под-объекта. Я бы знал, есть ли другое решение этой проблемы. Благодарю. Giuliano
Ваши подчеркивания сводят меня с ума. Кроме того, уверены ли вы, что это хороший способ оптимизации? Я думаю, что вам не хватает всего шаблона, если вам нужен скрипт для их создания! – vulkanino
Поскольку мне нужно поставить ключевое слово «статический» перед выбранными членами данных, а «статический» не является частью этого типа, для достижения этого невозможно использовать шаблонные трюки. По крайней мере, я думаю ... Спасибо! – Giuliano
Я думаю, вы должны попытаться описать то, что вы хотите достичь, потому что я думаю, что очень возможно, что есть намного более простой способ. –