2016-05-11 11 views
0

私は次のことのために、コードの重複を避けるためにしようとしています:テンプレート引数(ネストされたテンプレート)

template<class StringType, typename type1, typename type2, class MapType> 
void readDatastructure(MapType<type1, type2> map, const StringType path) { 
... some code 
} 

は、私は別のtype1type2パラメータを持っているいくつかの異なるマップタイプを持っています。ある時点で、どのタイプがtype1type2であるかを静的にチェックしたいので、このことをコンパイルする方法を理解できません。私はテンプレートの宣言にいくつかのバリエーションを試してみましたが、どれもうまくいかないようです。それも可能ですか?

乾杯、

+0

*いくつかの点で私は、静的 'type1'と' type2'であるかの種類をチェックしたい*のことを詳しく説明してください。 –

+0

私は 'std :: is_type'を使って、プログラムの中で私のコードの制御フローを決定したいと思っていました。 – XapaJIaMnu

答えて

3

あなたは

template<class StringType, typename type1, typename type2, 
     template<class, class> class MapType> 
void readDatastructure(MapType<type1, type2> map, const StringType path); 

の線に沿って何かをしたい。しかし、これは(コンパレータとアロケータのための)2つの追加テンプレートパラメータを有し、std::map、たとえば、動作しません。だから、どちらか

template<class StringType, typename type1, typename type2, 
     template<class...> class MapType> 
void readDatastructure(MapType<type1, type2> map, const StringType path); 

を行うか、すなわち、

template<class StringType, typename type1, typename type2, class C, class A, 
     template<class, class, class, class> class MapType> 
void readDatastructure(MapType<type1, type2, C, A> map, const StringType path); 

最初はまだデフォルト以外のコンパレータ/アロケータを取っstd::mapでは動作しません、余分なテンプレートパラメータを追加する必要があります。マップに4つのテンプレートタイプのパラメータが正確にない場合、2番目のテンプレートは機能しません。 unordered_map、これは5つあります。

したがって、地図タイプでこれらのタイプを公開する方が良いでしょう。 std::mapは、例えば、key_typemapped_typeと公開しています。 "publish"とはメンバーtypedefとして定義することです。そして、あなたは

template<class StringType, class MapType> 
void readDatastructure(MapType map, const StringType path); 

を書くことができるとtype1の代わりに、例えばtypename MapType::key_typeを使用しています。あなたのマップタイプを変更することはできません、と彼らは標準的なプロトコルに従わない場合は

、あなたは特性クラスを記述することができ、あなたのマップタイプのためにそれを特化:次にあなたがtypename map_traits<MapType>::key_typeを使用することができます

template<class T> 
struct map_traits { 
    using key_type = typename T::key_type; 
    using mapped_type = typename T::mapped_type; 
}; 
template<class T1, class T2> 
struct map_traits<MyBrokenMap<T1, T2>> { 
    using key_type = T1; 
    using mapped_type = T2; 
}; 

など

+0

あなたは出版物を詳しく説明できますか? – XapaJIaMnu

+0

ありがとう、これは非常に包括的な答えです! – XapaJIaMnu

1

テンプレートテンプレートパラメータ

template<class StringType, typename type1, typename type2, template <typename, typename > class MapType> 
1

すべてのstd ::マップタイプは、タイプkey_typemapped_typeを定義します。

テンプレート関数の拡張を制限するis_map特性を記述するのは簡単です。

例:

#include <iostream> 
#include <map> 
#include <unordered_map> 
#include <utility> 
#include <typeinfo> 


template<class Map> struct is_map 
{ 
    static constexpr bool value = false; 
}; 

template<class K, class V, class Comp, class Alloc> 
struct is_map<std::map<K, V, Comp, Alloc>> 
{ 
    static constexpr bool value = true; 
}; 

template<class K, class V, class Comp, class Hash, class Alloc> 
struct is_map<std::unordered_map<K, V, Comp, Hash, Alloc>> 
{ 
    static constexpr bool value = true; 
}; 

template< 
class Map, 
class String, 
std::enable_if_t<is_map<Map>::value>* = nullptr 
> 
void readDataStructure(Map& map, String&& path) 
{ 
    std::cout << "reading map with key type: " << typeid(typename Map::key_type).name() << std::endl; 
    std::cout << "  and with value type: " << typeid(typename Map::mapped_type).name() << std::endl; 
    std::cout << "--------------------------" << std::endl; 
} 


int main() 
{ 
    std::map<int, std::string> m1; 
    std::unordered_map<int, std::wstring> m2; 
    readDataStructure(m1, "foo.txt"); 
    readDataStructure(m2, "foo.txt"); 
} 

出力例:

reading map with key type: i 
     and with value type: NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE 
-------------------------- 
reading map with key type: i 
     and with value type: NSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEE 
-------------------------- 
関連する問題