I've got this test program
#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;
}
It fails to compile:
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);
^
I changed print() signature from (const C& c) to (C& c), it still fails:
$ 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);
^
How to fix it?
Your compilation problem arises because your template template parameter C
doesn't match the declaration of std::vector
:
template<
class T,
class Allocator = std::allocator<T>
> class vector;
As you can see, std::vector
has two template parameters, while your C
has only one. But, note as well that the second parameter (class Allocator
) has a default type argument. Since C++17, this is well-formed even the way you've written it, as it was added that template template parameters matching doesn't require specifying parameters for ones with default arguments like Allocator
. But not all compilers are supporting this modification to the language spec -- see here live how Clang 6.0.0 refuses to compile your original snippet with C++17 enabled. Going for older versions of C++ (or just any version to date of Clang), this snippet is probably what you were aiming for:
template<template<class, class> class C, typename T, typename A>
void print(const C<T, A>& c){
for(auto& e : c)cout<<e<<endl;
}
As here you specify the correct template signature of the type (std::vector
) you're later instantiating print()
with.
This would work too, regardless of C++17:
template<template<class...> class C, typename T>
void print(const C<T>& c){
for(auto& e : c)cout<<e<<endl;
}
That said, note that, as vector<int>
is already a fully instantiated type, this simpler version works just as well in the given scope of your snippet:
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:
This is probably the better practice in this case, as you're not modifying c
inside of print()
. However, this has nothing to do with your error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With