C ++模板的模板无法编译

时间:2018-09-15 13:24:15

标签: c++ templates compilation const

我有这个测试程序

#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);
                ^

如何解决?

2 个答案:

答案 0 :(得分:4)

您的编译问题出现是因为您的template template parameter Cstd::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允许使用默认模板参数来匹配模板模板参数较少的模板模板参数。

LIVE

在C ++ 17之前,您可以应用parameter pack

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

LIVE