关联容器作为函数模板参数

时间:2011-09-30 00:50:21

标签: c++ templates stl metaprogramming

我想知道如何编写一个函数,它可以接受一个本身接受两个或多个模板参数的关联容器作为参数。例如,如果我想编写一个适用于std :: map的函数,我可以编写如下所示的内容。

template <class Map, class Key, class Value, class Compare, class Allocator>
void foo(Map<Key, Value, Compare, Allocator>& map);

但是,这对boost :: unordered_map不起作用,因为boost :: unordered_map接受五个模板参数。我可以接受地图作为单个模板参数并使用它应该支持的特征以便稍后推断出键和值类型,但是对于嵌套映射,代码变得非常冗长且难以维护。有没有更简单的方法来编写这样的函数,但仍然可以使任何关联容器接受任何数量大于或等于2的模板参数?

请注意,接受迭代器而不是容器作为参数是不够的,因为我需要有关迭代器操作的容器的更多信息,而不是迭代器可以提供的信息。

非常感谢!

2 个答案:

答案 0 :(得分:2)

为什么不使用单个模板参数的简单方法:

template <typename C> void foo(const C & container)
{
  typedef typename C::key_type key_type;
  typedef typename C::mapped_type mapped_type;

  // etc.
}

您可以添加一些成员类型检查类型特征是否需要对这些成员类型存在的其他检查,但这可能不会带来任何额外的好处。

或者,您可以进行一些通用模式匹配,但只能使用类,而不是函数:

 template <typename> struct AtLeastTwo;

 template <typename K, typename V, typename ...Args>
 struct AtLeastTo<K, V, Args...>
 {
   // now have types K and V
 };

 typedef std::unordered_map<int, Foo, MyHash> map_type;
 AtLeastTwo<map_type> m;
 // ...

答案 1 :(得分:0)

类型不传达关于它是否是关联序列的信息,这是语义含义。如果您不支持所有类型的关联序列,根据标准接口,您最好的选择是使用单个模板参数并使用特征来内省其键/值类型等等。