我正在閱讀由Andrei Alexandrescu撰寫的Modern C++設計,我嘗試使用他給出的一些類型列表示例。在下面的例子中,我想創建一個包含一個類型和一個整數的Option
結構體的列表。後來我想創建這些選項的類型列表,然後將它們與一個整數一起傳遞給另一個結構體FindTypeForMapping
。如果整數與選項列表中設置的任何整數相匹配,則表達式應計算爲該選項的類型,否則應計算爲我的自定義類型NullType
。使用模板參數包而不是宏
第一種方法是將OptionsList
與宏創建,並有我對的Option
s各自數列表成立,其中每個宏n
Option
s的使用宏n-1
Option
s宏。
然後我想在模板參數中使用參數包到列表中。此版本的名單名爲OptionsList2
。在OptionsList2
我遞歸建立列表,但是當我通過這個列表FindTypeForMapping
時,我得到一個編譯時間錯誤(見下文)。
struct NullType { };
template<class T, class U>
struct OptionsList
{
typedef T Head;
typedef U Tail;
};
template<class T, class... U>
struct OptionsList2
{
typedef T Head;
typedef typename std::conditional<sizeof...(U) == 0, NullType, OptionsList2<U...>>::type Tail;
};
template<int n, typename N>
struct Option
{
enum {
int_mapping = n
};
typedef N MappedType;
};
template<int, int> struct CheckMappedInt;
template<int n>
struct CheckMappedInt<n, n>
{
enum { is_the_same = 1};
};
template<int n, int m>
struct CheckMappedInt
{
enum { is_the_same = 0};
};
template<typename OLT, int n> struct FindTypeForMapping;
template<int n>
struct FindTypeForMapping<NullType, n>
{
typedef NullType mapped_type;
};
template<typename OP, typename Tail, int n>
struct FindTypeForMapping<OptionsList<OP, Tail>, n>
{
private:
enum {temp = CheckMappedInt<OP::int_mapping, n>::is_the_same };
typedef typename FindTypeForMapping<Tail, n>::mapped_type temp_type;
public:
typedef typename std::conditional<
temp == 1,
typename OP::MappedType,
temp_type>::type mapped_type;
};
// Added this after SoryTellers comment
template<typename OP, typename Tail, int n>
struct FindTypeForMapping<OptionsList2<OP, Tail>, n>
{
private:
enum {temp = CheckMappedInt<OP::int_mapping, n>::is_the_same };
typedef typename FindTypeForMapping<Tail, n>::mapped_type temp_type;
public:
typedef typename std::conditional<
temp == 1,
typename OP::MappedType,
temp_type>::type mapped_type;
};
#define OPTION_LIST_1(op1) OptionsList<op1, NullType>
#define OPTION_LIST_2(op1, op2) OptionsList<op1, OPTION_LIST_1(op2)>
#define OPTION_LIST_3(op1, op2, op3) OptionsList<op1, OPTION_LIST_2(op2, op3)>
#define OPTION_LIST_4(op1, op2, op3, op4) OptionsList<op1, OPTION_LIST_3(op2, op3, op4)>
#define OPTION_LIST_5(op1, op2, op3, op4, op5) OptionsList<op1, OPTION_LIST_4(op2, op3, op4, op5)>
#define OPTION_LIST_6(op1, op2, op3, op4, op5, op6) OptionsList<op1, OPTION_LIST_5(op2, op3, op4, op5, op6)>
#define OPTION_LIST_7(op1, op2, op3, op4, op5, op6, op7) OptionsList<op1, OPTION_LIST_6(op2, op3, op4, op5, op6, op7)>
#define OPTION_LIST_8(op1, op2, op3, op4, op5, op6, op7, op8, op9) OptionsList<op1, OPTION_LIST_7(op2, op3, op4, op5, op6, op7, op8)>
#define OPTION_LIST_9(op1, op2, op3, op4, op5, op6, op7, op8, op9) OptionsList<op1, OPTION_LIST_8(op2, op3, op4, op5, op6, op7, op8, op9)>
int main(int argc, char* argv[])
{
typedef Option<1, char> o1;
typedef Option<2, int> o2;
// Works
typedef OPTION_LIST_2(o1, o2) ol;
typedef typename FindTypeForMapping<ol, 1>::mapped_type ResolvedType; // Works
typedef OptionsList2<o1, o2> ol2;
typedef typename FindTypeForMapping<ol2, 1>::mapped_type ResolvedType2;
/*
error: invalid use of incomplete type ‘struct FindTypeForMapping<Option<2, int>, 1>’
typedef typename FindTypeForMapping<Tail, n>::mapped_type temp_type;
*/
}
無論錯誤消息多麼複雜,您當然明白沒有專門的'FindTypeForMapping'接受'OptionsList2',只有'OptionsList'。這些是**不同的**模板! – StoryTeller
是的,謝謝。我添加了一個'FindTypeMapping'副本,接受一個'OptionsList2'。仍然是一個錯誤,但稍有不同。 錯誤:使用不完整類型的結構體FindTypeForMapping */ – Andreas
海事組織正在以錯誤的方式前進。而不是重複的東西,只專注於擺脫宏觀。添加一個'MakeOptionList'元函數,該元函數公開一個'OptionsList'作爲它的':: type'。然後你會擺脫宏觀。 –
StoryTeller