我有这个测试程序
#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);
^
如何解决?
答案 0 :(得分:4)
您的编译问题出现是因为您的template template parameter C
与std::vector
的声明不匹配:
template<
class T,
class Allocator = std::allocator<T>
> class vector;
如您所见, std::vector
有两个模板参数,而您的C
只有一个模板参数。但是,还要注意,第二个参数({{1} })具有 default 类型的参数。从C ++ 17开始,这甚至是您编写时的格式,因为添加了 template template parameters 匹配不需要为带有默认参数(例如{{ 1}}。但是,并非所有的编译器都支持对语言规范的此修改-请参见here live how Clang 6.0.0 refuses以在启用C ++ 17的情况下编译原始代码段。要使用C ++的旧版本(或Clang的任何最新版本),此代码段可能就是您的目标:
class Allocator
在这里,您可以指定类型(Allocator
)的正确模板签名,稍后使用该模板实例化template<template<class, class> class C, typename T, typename A>
void print(const C<T, A>& c){
for(auto& e : c)cout<<e<<endl;
}
。
无论C ++ 17如何,它也都可以工作:
std::vector
也就是说,请注意,由于print()
已经是完全实例化的类型,因此此更简单的版本在您的代码段的给定范围内同样有效:
template<template<class...> class C, typename T>
void print(const C<T>& c){
for(auto& e : c)cout<<e<<endl;
}
我将print()签名从
vector<int>
更改为template<typename T> void print(const T& c){ for(auto& e : c)cout<<e<<endl; }
,但仍然 失败:
在这种情况下,这可能是更好的做法,因为您没有在(const C& c)
内修改(C& c)
。但是,这与您的错误无关。
答案 1 :(得分:3)
std::vector
包含两个模板参数,而模板模板参数C
被声明仅包含一个。无论如何,您的代码可以在C ++ 17上正常工作。从C ++ 17(CWG 150开始,template template argument允许使用默认模板参数来匹配模板模板参数较少的模板模板参数。
在C ++ 17之前,您可以应用parameter pack。
template<template<class...> class C, typename T>
void print(const C<T>& c){
for(auto& e : c)cout<<e<<endl;
}