模板函数接受任何类似于map <x,y =“”> </x,>的类型

时间:2011-11-07 00:40:49

标签: c++ templates

有没有办法让这样的工作:

template<typename T, typename X, typename Y>
void myFunc(T<X,Y> map, X x, Y y) {
    map[x] += y;
}

基本上我希望任何类似map<X,Y>的内容都是有效的输入。

这可能吗?

我收到此错误但我不知道这意味着什么:

  

test.cpp:2:17:错误:'T'不是模板

3 个答案:

答案 0 :(得分:4)

是,使用模板模板模板参数:

template <template <typename, typename> class M, typename K, typename V>
void Foo(M<K, V> & container)
{
  // ...
};

请注意,这永远不会匹配任何真实单词容器,因为它们有更多的模板参数。可变参数更好:

template <template <typename, typename, typename...> class M, typename K, typename V, typename ...Args>
void Foo(M<K, V, Args...> & container)
{
  // ...
};

如果variadics不是一个选项,你可以自己利用一些包装:

template <typename Container> void FooImpl(Container &);

template <template <typename, typename> class M,
          typename K, typename V>
void Foo(M<K,V> & c) { FooImpl(c); }

template <template <typename, typename, typename> class M,
          typename K, typename V, typename A1>
void Foo(M<K,V,A1> & c) { FooImpl(c); }

template <template <typename, typename, typename, typename> class M,
          typename K, typename V, typename A1, typename A2>
void Foo(M<K,V,A1,A2> & c) { FooImpl(c); }

// etc.

作为参考,std::unordered_map需要五个模板参数(键,值,散列函数,等式谓词,分配器)。提升的bimap可能需要更多。

通过使函数成为包装类的静态成员并使实现变为私有,并通过提供单个免费访问器辅助函数,可以防止滥用此最后一个结构。

答案 1 :(得分:3)

最简单的方法是仅使用T作为参数类型。

template<typename T, typename X, typename Y>
void myFunc(T map, X x, Y y) {
    map[x] += y;
}

请注意,这将允许例如。数组为T s(例如。T = int*, X = int, Y = int,该函数会将y添加到数组x的{​​{1}}元素。

如果你想将它缩小到地图,你必须根据你决定一张地图。识别地图的一种可能性是检查他们的mapkey_type。例如:

mapped_type

如果你真的想接受任何带有两个类型参数(而不是更多)的东西,你可以使用模板模板参数。但是,我认为这是一种过于语法的区别,除非您打算使用多个参数类型实例化template-template参数,否则不应该使用它。

答案 2 :(得分:1)

如果你没有将map约束为T类,事情会变得简单得多:

template<typename T, typename X, typename Y>
void myFunc(T map, X x, Y y) {
    map[x] += y;
}

// ...

map<int, int> myMap;
myFunc(myMap, 5, 7);

std :: map实际上有比K和V更多的参数(它还有一个比较器和一个分配器),所以最好不要匹配它的模板参数。上面的代码仍然只编译那些有非const运算符[]的东西,以X作为键并返回Y作为值,但它对于非特定容器的容器也是灵活的,例如Container