c++:为什么不能使用模板来推断容器和元素类型?

c++: why template cannot be used to deduce both container and element type?

我有一个非常简单的测试程序,如下所示:

#include<vector>
#include<iostream>
using namespace std;
template<typename C, typename E>
void f(const C<E>& container){
    cout<<container.size()<<endl;
}
int main(){
    vector<int> i;
    f(i);
    return 0;
}

使用gcc 4.1.2 编译失败。错误信息是:

templateContainer.cpp:5: error: ‘C’ is not a template
templateContainer.cpp: In function ‘int main()’:
templateContainer.cpp:10: error: no matching function for call to ‘f(std::vector<int, std::allocator<int> >&)’

您可以使用 模板模板参数 (请注意 std::vector 实际上采用多个模板参数 [一种元素类型和一种分配器类型])。 :

template<template <typename...> class C, typename... E>
void f(const C<E...>& container){
    cout<<container.size()<<endl;
}

Live Demo


如果不需要类型分解,可以简单地使用普通模板。

template<typename C>
void f(const C& container){
    cout<<container.size()<<endl;
}

您还可以从 STL 容器中获取 typedef:例如,如果您想知道容器持有的元素的 typevalue_type 就在那里.

template<typename C>
void f(const C& container){
    using ValueType = typename C::value_type;
    cout<<container.size()<<endl;
}

std::vector 有两个模板参数,类型和分配器。

template <template<class, class> class C, class E, class A>
void f(const C<E, A> &container) 
{
   std::cout << container.size() << endl;
}

int main()
{
   std::vector<int> i;
   f(i);
   return 0;
}

虽然 WhiZTiM 的回答是正确的(好吧,更喜欢第二部分),但它没有解释为什么你的代码不起作用。

暂时假设您的意图是粗略的

template<template <typename> class C, typename E> void f(const C<E>&);

std::vector 不匹配的原因是它的形状错误 - 它有两个类型参数,而不是您声明中的一个。

仅仅因为您不经常显式编写默认的第二个(分配器)参数,并不意味着它不存在。

为了比较,这以类似的方式工作(或不工作):

void f(int);
void g(int, int* = nullptr);

void apply(void (*func)(int), int);

apply(f, 42); // ok - f matches shape void(*)(int)
apply(g, 42); // error - g is really void(*)(int,int*)

具体来说,默认参数(或类型参数)是语法糖。它们允许您在调用(实例化)站点忘记那些参数,但不要更改函数(或模板)的形状。