我正在尝试实现一个像 std::pair 这样的类,但有两个以上的组件。由于在我的应用程序中可能会发生一些元组组件在编译时已经知道,我希望进行以下空间优化:当我知道一个组件是编译时常量时,只需将其声明为 ' static const' 成员,因此它不会浪费单个类实例中的存储空间。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;
这样,标记为 constant<.,.> 的成员不会存储为类成员,从而减小了对象大小。所需的部分专业化数量可能很大,N=1,2,3,4 时需要 2^N,我只报告最多 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 作为子对象。我想知道这个问题是否有另一种解决方案。谢谢。朱利亚诺