2017-10-08 12 views
0

私はModern C++デザインをAndrei Alexandrescuが読んでいます。私は彼が与えているタイプリストの例をいくつか使用しようとしています。下の例では、型と整数を保持するOption構造体のリストを作成します。後でそれらのオプションのタイプリストを作成し、それを別の構造体FindTypeForMappingに整数と共に渡したいとします。整数がオプションのリストに設定されている整数のいずれかと一致する場合、その式はそのオプションのタイプに評価される必要があります。そうでない場合は、カスタムタイプNullTypeと評価されます。作品マクロの代わりにテンプレートパラメータパックを使用する

最初のアプローチはOptionsListが、マクロで作成され、そこに私はnOptionのための各マクロがn-1Option秒間マクロを使用しているリストを保持している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; 
    */  
} 
+1

単にのように記述することができますエラーメッセージの複雑さにかかわらず、確実に、 'OptionsList2'を受け入れる' FindTypeForMapping'の特化はなく、 'OptionsList'だけを理解しています。それらは**異なる**テンプレートです! – StoryTeller

+0

はい、ありがとうございます。 'OptionsList2'を受け入れる' FindTypeMapping'のコピーを追加しました。それでもやはりエラーですが少し異なります。 /* エラー:不完全な型 'struct FindTypeForMapping

+0

これは間違った方向に向かっているIMOです。ものを複製するのではなく、マクロを取り除くことに集中してください。 'OptionsList'を' :: type'として公開する 'MakeOptionList 'メタ関数を追加してください。その後、マクロを取り除きます。 – StoryTeller

答えて

1

申し訳ありませんが...なぜあなたは単にstd::tuple代わりに可変引数OptionList2を使用していませんか?以下の(FTFMで私は短い名前場合は申し訳ありません)

template <typename, int> 
struct FTFM; 

template <int n, int no, typename TypeO, typename ... Ts> 
struct FTFM<std::tuple<Option<no, TypeO>, Ts...>, n> 
{ using type = typename FTFM<std::tuple<Ts...>, n>::type; }; 

template <int n, typename TypeO, typename ... Ts> 
struct FTFM<std::tuple<Option<n, TypeO>, Ts...>, n> 
{ using type = TypeO; }; 

template <int n> 
struct FTFM<std::tuple<>, n> 
{ using type = NullType; }; 

がいっぱい働いている

あなたFindTypeForMapping型形質は(も...コンパイル)の例

#include <tuple> 
#include <type_traits> 

struct NullType 
{ }; 

template <int n, typename T> 
struct Option : public std::integral_constant<int, n> 
{ using type = T; }; 

template <typename, int> 
struct FTFM; 

template <int n, int no, typename TypeO, typename ... Ts> 
struct FTFM<std::tuple<Option<no, TypeO>, Ts...>, n> 
{ using type = typename FTFM<std::tuple<Ts...>, n>::type; }; 

template <int n, typename TypeO, typename ... Ts> 
struct FTFM<std::tuple<Option<n, TypeO>, Ts...>, n> 
{ using type = TypeO; }; 

template <int n> 
struct FTFM<std::tuple<>, n> 
{ using type = NullType; }; 

template <typename T, int I> 
using FTFM_t = typename FTFM<T, I>::type; 

int main() 
{ 
    using opt0 = Option<0, void>; 
    using opt1 = Option<1, char>; 
    using opt2 = Option<2, short>; 
    using opt3 = Option<3, int>; 
    using opt4 = Option<4, long>; 
    using opt5 = Option<5, long long>; 

    using optList = std::tuple<opt0, opt1, opt2, opt3, opt4, opt5>; 

    static_assert (std::is_same<void,  FTFM_t<optList, 0>>{}, "!"); 
    static_assert (std::is_same<char,  FTFM_t<optList, 1>>{}, "!"); 
    static_assert (std::is_same<short,  FTFM_t<optList, 2>>{}, "!"); 
    static_assert (std::is_same<int,  FTFM_t<optList, 3>>{}, "!"); 
    static_assert (std::is_same<long,  FTFM_t<optList, 4>>{}, "!"); 
    static_assert (std::is_same<long long, FTFM_t<optList, 5>>{}, "!"); 
    static_assert (std::is_same<NullType, FTFM_t<optList, 6>>{}, "!"); 
} 
+0

ありがとうございます。 NiceListは、OptionsListとCheckedMappedIntを削除します。 – Andreas

関連する問題