问题
#include <cstdint>
#include <iostream>
class MyBar {
public:
void print() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
template <class Bar = MyBar>
class Foo{
public:
Foo(const char* name, const uint32_t i) {
Bar b;
b.print();
}
};
int main(int argc, char** argv) {
auto pFoo1 = new Foo("abc", 3);
}
Compiler gave me:
template_ctor.cpp: In function ‘int main(int, char**)’:
template_ctor.cpp:21:31: error: class template argument deduction failed:
auto pFoo1 = new Foo("abc", 3);
^
template_ctor.cpp:21:31: error: no matching function for call to ‘Foo()’
template_ctor.cpp:14:2: note: candidate: template<class Bar> Foo(const char*, uint32_t)-> Foo<Bar>
Foo(const char* name, const uint32_t i) {
^~~
template_ctor.cpp:14:2: note: template argument deduction/substitution failed:
template_ctor.cpp:21:31: note: candidate expects 2 arguments, 0 provided
auto pFoo1 = new Foo("abc", 3);
As soon as I put <>
after new Foo
, it compiles.
At first, I thought <>
is mandatory to hint the compiler to use the default template parameter, but then I noticed that if I drop const char* name
and then I don't pass in "abc"
, then it also compiles.
Now, I am confused.
回答1:
This should compile, and is basically gcc bug 85883. This has been fixed on trunk:
struct MyBar;
template <class Bar = MyBar>
class Foo{
public:
Foo(const char* name, int i);
};
auto pFoo1 = new Foo("abc", 3);
The example fails on gcc 8.2, but compiles on 9.
回答2:
The compiler uses the information it has at instantiation time for the deduction.
In the case of new Foo("abc", 3)
it really only have the constructor argument types, none of which are templated. Therefore you need to use new Foo<>("abc", 3)
to explicitly say that no template type is specified and the default type should be used.
This usage have been in C++ since default template argument types was introduced.
If one of the constructor arguments were of the template type, then the compiler should be able to deduce the template type from that argument.
来源:https://stackoverflow.com/questions/54389395/template-argument-deduction-failed-with-default-template-parameter