2016-11-01 19 views
2

に応じたクラスのメンバタイプを定義します。C++、我々は以下のクラスを持っている我々のコードでは、そのテンプレート

template<class A, class B> 
class myClass 
{ 
    typedef std::list<Object<A,B>> MyList; 
    typedef std::map<A, typename mList::iterator> MyMap 

    MyList mList; 
    MyMap mMap; 
} 

クラスAがmetaprogrammedされ、それはように、文字列、int型とすることができます。 クラスAが "メタ文字列"の場合はマップを使用します。そうでない場合は、unordered_mapが使用されます。

私はいくつかのより多くのメタプログラミングを追加しようとしましたが、まだ成功していない:別のマップタイプを使用するための

template< class A, class B> 
struct MapType // default 
{ 
    typedef std::list<Object<A,B>> MyList; 
    typedef std::unordered_map<A,B> MyMap; 
} 

//TODO struct with templated A (string) to use std::map 

template<class A, class B> 
class myClass 
{ 
    ???? // if A ~ String define myMap to MAP . otherwise unordered 

    MyList mList; 
    MyMap mMap; 
} 

他の提案も同様に理解されるであろう。

おかげ

+2

正確に「メタ文字列」とは何ですか?特定のクラスですか?特定のインターフェイスを実装するクラスですか?特定のプロパティを持つクラス? – celtschk

+1

最初のコードブロックで、 'MyMap'をこの' typedef std :: map MyMap'のように定義するべきではありませんか? – Danh

答えて

3

(私はデモの目的のためにstd::stringを選んだ)簡単な解決策は、Aがあなたの「メタ文字」クラスと同じであるかどうかを確認するためにstd::conditionalを使用することです:

template<class A, class B> 
class myClass 
{ 
    std::list<Object<A,B>> mList; 
    std::conditional_t<std::is_same<A,std::string>::value, 
         std::map<A,B>, std::unordered_map<A,B>> mMap; 
}; 

別の可能性は、部分的な専門化を使用することです:

template<class A, class B> 
class myClass 
{ 
    std::list<Object<A,B>> mList; 
    std::unordered_map<A,B> mMap; 
}; 

template<class B> 
class myClass<std::string,B> 
{ 
    std::list<Object<std::string,B>> mList; 
    std::map<std::string,B> mMap; 
}; 
+0

答えをありがとう。それは非常に有用です。 –

2

使用std::conditonalトレイト:

template<class A, class B> 
class myClass 
{ 
    using MyList = std::list<Object<A,B>>; 
    using MyMap = std::conditional_t<IsMetaString<A>::value, 
         std::map<A, typename mList::iterator>, 
         std::unordered_map<A, typename mList::iterator>>; 

    MyList mList; 
    MyMap mMap; 
} 

私はあなたがあまりにも行う必要があります使用したタイプの別名、とあなたのtyedefsを置き換えるために自由を取ったのでご注意ください。メタ文字列によって、あなたがstd::stringを意味する場合は、インスタンスのための

template <class T> struct IsMetaString : std::false_type {}; 
template <> struct IsMetaString<std::string> : std::true_type {}; 

:残っているもの

は、メタ文字列のあなたの定義に依存するのと同じくらい簡単かもしれないIsMetaStringを実装することです。または、必要に応じて変更することもできます。

また、typename mList::iteratorではなくtypename MyList::iteratorを意味すると思います。 「メタ文字列は」あなたは「メタ文字列は」何であるかを指定していないので、あなたは、単に部分的で

template< class A, class B> 
struct MapType // default 
{ 
    typedef std::list<Object<A,B>> MyList; 
    typedef std::unordered_map<A,B> MyMap; 

    MyList mList; 
    MyMap mMap; 
}; 


template<class B> 
struct MapType<foo, B> 
{ 
    typedef std::list<Object<foo, B>> MyList; 
    typedef std::map<foo,B> MyMap; 

    MyList mList; 
    MyMap mMap; 
}; 
+0

あなたは私の答えを下降させなければならないと感じたので、その内容が別のメンバーの投稿に組み込まれていることに基づいて、私は好意を返す。結局のところ、あなたの投稿の内容も本質的に彼/彼女のものです。私は自分の投稿を入力する過程で気を散らしていたので、投稿する前にあなたのどちらも見なかった。 – Peter

+0

@Peterはあなたの右です – bolov

+0

ビンゴ。しかし、一般的には、間違った/無効な回答のみをダウンボートすることを目指しています。しかし、あなたはそのような懲罰的な方法であなたのダウンフォートを使いました。私は親切に答えました。 – Peter

0

(pre-C++ 11ではstd :: conditionalを持たないかもしれませんが)特殊化(クラス全体を特殊化する必要はありませんが、多くのメソッドをコピーするのに大きな負担になるかもしれませんが)マップの種類:

template<class A, class B> 
class myClass 
{ 
    template<class X, class ITER_T> 
    struct map_type { 
     typedef std::map<X, ITER_T> type; 
    }; 

    template<class ITER_T> 
    struct map_type<std::string, ITER_T> { 
     typedef boost::unordered_map<A /* or std::string */, ITER_T> type; 
    }; 

    typedef std::list<Object<A,B>> MyList; 
    typedef map_type<A, typename MyList::iterator>::type MyMap; 

    MyList mList; 
    MyMap mMap; 
}; 

(for pre-C++ 11 std::unordered_mapの代わりにboost::unordered_mapを使用します)

+0

申し訳ありませんが、私はdownvoteする必要があります。あなたの答えはあなたの前に投稿された 'TartanLlama'の答えに組み込まれています。私と彼は基本的に同じ答えを持っていますが、同時にほぼ同時に投稿しました。 – bolov

+0

お返事ありがとう –

0

を行うことができますが、私はちょうど作っ架空の名前(fooを入力していると仮定すると、

+0

ありがとうございました。私はおそらくメソッドの組み合わせを使用し、おそらくあなたの答えに条件付きのおかげでの使用を避けるためにしようとします。 –

+0

申し訳ありませんが、私は...のテンプレートのparmの宣言を取得し続けます。 内側のテンプレートは外側のテンプレートをシャドウします。これをどうすれば解決できますか? –

+1

@FPGaleroちょうど 'map_type'のためのテンプレートパラメータの名前を変更してください:) – TartanLlama

関連する問題