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

时间:2017-06-20 14:00:59

标签: c++ class templates containers typename

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

vidPath = "android.resource://" + getPackageName() + "/" + "/raw/" + path;

无法使用gcc 4.1.2进行编译。错误信息是:

#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;
}

3 个答案:

答案 0 :(得分:10)

您可以使用模板模板参数(并注意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:例如,如果您想知道容器所拥有的元素的类型,那么value_type就可以了。

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

答案 1 :(得分:1)

std :: vector有两个模板参数,type和allocator。

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;
}

答案 2 :(得分:1)

虽然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*)

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