也接受模板的模板参数(嵌套模板)
Template argument that takes templates as well (nested templates)
我正在努力避免代码重复,原因如下:
template<class StringType, typename type1, typename type2, class MapType>
void readDatastructure(MapType<type1, type2> map, const StringType path) {
... some code
}
我有几种不同的地图类型,它们具有不同的 type1
和 type2
参数。在某些时候,我想静态检查 type1
和 type2
是什么类型,但我不知道如何编译这个东西。我已经尝试了该模板声明的几种变体,其中 none 似乎有效。这可能吗?
干杯,
你想要
template<class StringType, typename type1, typename type2,
template<class, class> class MapType>
void readDatastructure(MapType<type1, type2> map, const StringType path);
但这不适用于 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
采用非默认值 comparator/allocators;如果您的地图没有恰好有四个模板类型参数,则第二个不起作用 - 例如unordered_map
,其中有五个。
因此,最好让您的地图类型发布这些类型。 std::map
,例如,将它们发布为 key_type
和 mapped_type
。 "publish",我的意思是将它们定义为成员类型定义。然后你可以写
template<class StringType, class MapType>
void readDatastructure(MapType map, const StringType path);
并使用 typename MapType::key_type
代替 type1
。
如果您不能更改您的地图类型,并且它们不遵循标准协议,您可以编写一个特征 class 并针对您的地图类型专门化它:
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;
};
那你可以用typename map_traits<MapType>::key_type
等
模板模板参数
template<class StringType, typename type1, typename type2, template <typename, typename > class MapType>
所有 std::map 类型定义类型 key_type
和 mapped_type
.
写一个is_map trait 来约束模板函数展开就很简单了
示例:
#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
--------------------------
我正在努力避免代码重复,原因如下:
template<class StringType, typename type1, typename type2, class MapType>
void readDatastructure(MapType<type1, type2> map, const StringType path) {
... some code
}
我有几种不同的地图类型,它们具有不同的 type1
和 type2
参数。在某些时候,我想静态检查 type1
和 type2
是什么类型,但我不知道如何编译这个东西。我已经尝试了该模板声明的几种变体,其中 none 似乎有效。这可能吗?
干杯,
你想要
template<class StringType, typename type1, typename type2,
template<class, class> class MapType>
void readDatastructure(MapType<type1, type2> map, const StringType path);
但这不适用于 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
采用非默认值 comparator/allocators;如果您的地图没有恰好有四个模板类型参数,则第二个不起作用 - 例如unordered_map
,其中有五个。
因此,最好让您的地图类型发布这些类型。 std::map
,例如,将它们发布为 key_type
和 mapped_type
。 "publish",我的意思是将它们定义为成员类型定义。然后你可以写
template<class StringType, class MapType>
void readDatastructure(MapType map, const StringType path);
并使用 typename MapType::key_type
代替 type1
。
如果您不能更改您的地图类型,并且它们不遵循标准协议,您可以编写一个特征 class 并针对您的地图类型专门化它:
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;
};
那你可以用typename map_traits<MapType>::key_type
等
模板模板参数
template<class StringType, typename type1, typename type2, template <typename, typename > class MapType>
所有 std::map 类型定义类型 key_type
和 mapped_type
.
写一个is_map trait 来约束模板函数展开就很简单了
示例:
#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
--------------------------