c ++模板到模板参数

时间:2013-12-31 06:15:40

标签: c++ templates compiler-construction compiler-errors

最近我测试了一些c ++模板代码,我发现了一个令人难以置信的错误。根据我对互联网特别是stackoverflow的研究,这段代码完全有效,但编译器会引发编译时错误。错误位于代码下方。

代码:

template<template<class> class C, typename T> void print(C<T>& c) {
}

int test() {
    vector<string> v(5, "Yow!");
    print(v);
    return 0;
}

编译器输出:

In function ‘int test()’:
error: no matching function for call to ‘print2(std::vector<std::basic_string<char> >&)’
note: candidate is:
note: template<template<class> class C, class T> void print2(C<T>&)

似乎定义或编译器出了问题,但我用g ++和clang ++测试了这段代码,以确保没有任何编译器相关的问题。它们都引发了同样的错误。

我非常感谢任何有意义的评论,旨在澄清这个问题。

谢谢

2 个答案:

答案 0 :(得分:3)

std::vector,以C传入的类型具有多个模板参数。它具有通常的元素类型,但也是一个分配器。在保留类型参数列表的同时解决此问题的最简单方法是使用可变参数模板:

template<template<class...> class C, typename... Ts> void print(C<Ts...>& c)
                  ^^^^^^^^                   ^^^^^^             ^^^^^^^^

实际上,在大多数情况下,通过明确指定它们,使用单个类型参数更容易,如在Cheers的答案中。如果您不关心类型参数,请随时不要跟踪它们。对于容器,您甚至可以从容器类型中获取它们:

template<typename Container> void print(Container& c) {
    typename Container::value_type t;
}

答案 1 :(得分:2)

chris' answer上扩展,以下编译与visual c ++ 12.0和g ++ 4.7.2一起使用时很好:

#include <vector>
#include <string>
using namespace std;

template<template<class, class> class C, class T, class U> void print(C<T, U>& c)
{ (void) c; }

void test() {
    vector<string> v(5, "Yow!");
    print(v);
}

但是,如果你真的只想输出容器的项目,为什么不这样做呢:

#include <iostream>
#include <vector>
#include <string>
using namespace std;

template< class C >
void print( C const& c )
{
    for( auto const& item : c )
    {
        cout << item << endl;
    }
}

auto main() -> int
{
    vector<string> v(5, "Yow!");
    print(v);
}