私はModern C++デザインをAndrei Alexandrescuが読んでいます。私は彼が与えているタイプリストの例をいくつか使用しようとしています。下の例では、型と整数を保持するOption
構造体のリストを作成します。後でそれらのオプションのタイプリストを作成し、それを別の構造体FindTypeForMapping
に整数と共に渡したいとします。整数がオプションのリストに設定されている整数のいずれかと一致する場合、その式はそのオプションのタイプに評価される必要があります。そうでない場合は、カスタムタイプNullType
と評価されます。作品マクロの代わりにテンプレートパラメータパックを使用する
最初のアプローチはOptionsList
が、マクロで作成され、そこに私はn
Option
のための各マクロがn-1
Option
秒間マクロを使用しているリストを保持しているOption
秒数ごとのマクロを、持っているということです。
次に、テンプレートパラメータのパラメータパックをリストに使用したかったのです。このバージョンのリストの名前は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;
*/
}
単にのように記述することができますエラーメッセージの複雑さにかかわらず、確実に、 'OptionsList2'を受け入れる' FindTypeForMapping'の特化はなく、 'OptionsList'だけを理解しています。それらは**異なる**テンプレートです! – StoryTeller
はい、ありがとうございます。 'OptionsList2'を受け入れる' FindTypeMapping'のコピーを追加しました。それでもやはりエラーですが少し異なります。 /* エラー:不完全な型 'struct FindTypeForMapping
これは間違った方向に向かっているIMOです。ものを複製するのではなく、マクロを取り除くことに集中してください。 'OptionsList'を' :: type'として公開する 'MakeOptionList'メタ関数を追加してください。その後、マクロを取り除きます。 –
StoryTeller