C模板的模板无法编译

我有这个测试程序

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

template<template<class> class C, typename T>
void print(const C<T>& c){
    for(auto& e : c)cout<<e<<endl;
}
int main(){
    vector<int> v;
    print(v);
    return 0;
}

它无法编译:

g++ m.cpp -std=c++11
m.cpp: In function ‘int main()’:
m.cpp:11:16: error: no matching function for call to ‘print(std::vector<int>&)’
        print(v);
                ^
m.cpp:6:6: note: candidate: template<template<class> class C, class T> void print(const C<T>&)
void print(const C<T>& c){
    ^~~~~
m.cpp:6:6: note:   template argument deduction/substitution failed:
m.cpp:11:16: note:   template parameters of a template template argument are inconsistent with other deduced template arguments
        print(v);
                ^

我将print()签名从(const C& c)更改为(C& c),它仍然失败:

$g++ m.cpp -std=c++11
m.cpp: In function ‘int main()’:
m.cpp:11:16: error: no matching function for call to ‘print(std::vector<int>&)’
        print(v);
                ^
m.cpp:6:6: note: candidate: template<template<class> class C, class T> void print(C<T>&)
void print(C<T>& c){
    ^~~~~
m.cpp:6:6: note:   template argument deduction/substitution failed:
m.cpp:11:16: note:   template parameters of a template template argument are inconsistent with other deduced template arguments
        print(v);
                ^

怎么解决?

解决方法:

您的编译问题出现是因为您的template template parameter C与std :: vector的声明不匹配:

template<
    class T,
    class Allocator = std::allocator<T>
> class vector;

如您所见,std :: vector有两个模板参数,而您的C只有一个.但是,请注意第二个参数(类Allocator)具有默认类型参数.从C17开始,即使你编写它也是很好的形式,因为添加模板模板参数匹配不需要为具有默认参数(如Allocator)的参数指定参数.但并非所有编译器都支持对语言规范的修改 – 请参阅here live how Clang 6.0.0 refuses以编译启用了C 17的原始代码段.寻找旧版本的C(或者只是Clang的任何版本),这个片段可能就是你的目标:

template<template<class, class> class C, typename T, typename A>
void print(const C<T, A>& c){
    for(auto& e : c)cout<<e<<endl;
}

在这里,您指定类型(std :: vector)的正确模板签名,您稍后将使用实例化print().

无论C 17如何,这都会有效:

template<template<class...> class C, typename T>
void print(const C<T>& c){
    for(auto& e : c)cout<<e<<endl;
}

也就是说,请注意,作为vector< int>已经是完全实例化的类型,这个更简单的版本在您的代码段的给定范围内也可以正常工作:

template<typename T>
void print(const T& c){
    for(auto& e : c)cout<<e<<endl;
}

I changed print() signature from (const C& c) to (C& c), it still
fails:

在这种情况下,这可能是更好的做法,因为你没有修改print()中的c.但是,这与您的错误无关.

上一篇:c – 单个文件库的目标文件(.o)vs头文件?


下一篇:c – 如果不需要,请避免在Make中链接和编译