首页 > 解决方案 > 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);
                ^

如何解决?

标签: c++templatescompilationconstants

解决方案


出现编译问题是因为您的模板模板参数 C与以下声明不匹配std::vector

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

如您所见,std::vector有两个模板参数,而您C只有一个。但是,还要注意第二个参数 ( class Allocator) 有一个默认类型参数。从 C++17 开始,即使您编写它的方式也是格式良好的,因为添加了模板模板参数匹配不需要为具有默认参数的参数指定参数,例如Allocator. 但并非所有编译器都支持对语言规范的这种修改——在此处实时查看 Clang 6.0.0 如何拒绝在启用 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;
}

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

在这种情况下,这可能是更好的做法,因为您没有cprint(). 但是,这与您的错误无关。


推荐阅读