我想實現一個像std :: pair但有兩個以上組件的類。由於在我的應用程序中可能會發生某些元組件在編譯時已經知道,我想要進行以下空間優化:當我知道某個組件是編譯時常量時,只需將其聲明爲「靜態常量「成員,這樣它就不會浪費存儲在各個類實例中。 const限定符確保在運行時修改該值的任何嘗試都會導致編譯錯誤,至少如果我們排除不禮貌的const_cast(s)。編譯時常量的優化
我結束了下面的實現,一個n元組類
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_;
};
和一堆n元組類
的部分特例的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;
這樣標記爲常量的成員<。,。>不作爲類成員存儲,因此減少了對象大小。需要的部分專業化的數量可能很大,對於N = 1,2,3,4,我只報告N = 2的2^N:我寫了一個簡單的腳本來生成所有這些。這個類可以使用如下:
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));
像這樣,這個類的作品完美。現在,我只是想提高n元組的聲明 語法如下
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_等。這是可行的,但以成本部分專業化數量的因子增加。我想改變n元組類的定義如下
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; };
,並專注n元組如下
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作爲子對象。我會知道是否有另一個解決這個問題的方法。謝謝。朱利亞諾
你的下劃線讓我瘋狂。此外,你確定這是一個優化的好方法嗎?如果您需要腳本來生成它們,我認爲您錯過了整個模板點! – vulkanino 2012-03-02 13:53:06
由於我需要將關鍵字'靜態'放在所選數據成員的前面,'靜態'不是該類型的一部分,因此無法使用模板技巧來實現此目的。至少,我想......謝謝! – Giuliano 2012-03-02 14:13:40
我想你應該試着描述一下你想達到的目標,因爲我認爲這很可能有一個更簡單的方法。 – 2012-03-02 14:40:57