Compiling this:
#include <iostream>
#include <memory>
template <auto val = 42>
struct A
{
A()
{
std::cerr << val << "\n";
}
};
int main(int argc, const char* argv[])
{
std::shared_ptr<A> a_ptr {new A {}};
return 0;
}
gives error: use of class template 'A' requires template arguments
. Although I provide a default value for non-type template parameter and expect it to be seen and used by compiler somehow. What do I miss here?
Thanks.
It's still a template, and it still requires <
and >
:
std::shared_ptr<A<>> a_ptr {new A<> {}};
Think about this. If you have a function with a default parameter:
int foo(int baz=42);
Do you think you can simply call it without the parenthesis?
int foobar=foo;
Of course not, this won't work. You still need the parenthesis:
int foobar=foo();
Same thing with templates.
A
doesn't name a class
, it names a class template.
You need to use A<>
to name the instantiation of the template that uses the default value:
std::shared_ptr<A<>> a_ptr {new A<> {}};
// ^~~ here and ^~~ here
If you are in c++17 or above, as is implied by the auto
template parameter, you may remove the <>
from A
's construction since this qualifies as CTAD, but it's still needed in the type for shared_ptr
std::shared_ptr<A<>> a_ptr {new A {}};
// ^~~ only here
Note: This only applies if there is no ambiguity to the type. If a constructor qualifies for CTAD, this will deduce a (possibly different) type than A<>
For example, if A
were defined as:
template <typename T = int>
struct A
{
A(){}
A(T x){}
};
Then:
std::shared_ptr<A<>> a_ptr {new A {}};
would succeed, but
std::shared_ptr<A<>> a_ptr {new A {0.1}};
would fail, since new A {0.1}
deduces A<double>
, but A<>
names A<int>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.