The following stripped down code doesn't work with the latest clang++5 but is accepted by g++7:
template<typename Wrapped, typename U>
struct wrapper;
template<typename Wrapped, typename U=int>
struct wrapper
{
wrapper() = default;
// Automatic deduction guide
constexpr explicit wrapper(Wrapped) noexcept {}
};
int main()
{
struct {} dummy;
constexpr auto wrapped = wrapper(dummy);
}
It fails with the following error messages:
<source>:18:30: error: no viable constructor or deduction guide for deduction of template arguments of 'wrapper'
constexpr auto wrapped = wrapper(dummy);
^
<source>:12:24: note: candidate template ignored: couldn't infer template argument 'U'
constexpr explicit wrapper(Wrapped) noexcept {}
^
<source>:4:8: note: candidate template ignored: could not match 'wrapper<Wrapped, U>' against '(anonymous struct at <source>:17:5)'
struct wrapper;
^
<source>:9:5: note: candidate function template not viable: requires 0 arguments, but 1 was provided
wrapper() = default;
^
However if I move the default template parameter =int
from the class template definition to the forward declaration, everything works perfectly (U
being deduced to int
as expected), as if only the default template parameter in the forward declaration was taken into account when create the set of fictional function templates used by deduction guides.
I tried to read the standard wording but couldn't get much out of it for this specific case. Is only taking the default template parameter in the forward declaration the intended behaviour when generating the fictional function templates, or is this a compiler bug?
Template argument deduction is used when selecting user-defined conversion function template arguments. A is the type that is required as the result of the conversion. P is the return type of the conversion function template.
You cannot give default arguments to the same template parameters in different declarations in the same scope. The compiler will not allow the following example: template<class T = char> class X; template<class T = char> class X { };
Can default arguments be used with the template class? Explanation: The template class can use default arguments.
In C++ this can be achieved using template parameters. A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
This is not a quote of the Standard per se1, but I feel confident enough to consider it an answer.
According to cppreference, on Default template arguments:
Default template arguments that appear in the declarations and the definition are merged similarly to default function arguments:
template<typename T1, typename T2 = int> class A; template<typename T1 = int, typename T2> class A; // the above is the same as the following: template<typename T1 = int, typename T2 = int> class A;
But the same parameter cannot be given default arguments twice in the same scope
template<typename T = int> class X; template<typename T = int> class X {}; // error
This implies an implicit rule: A template type argument can be given a default type in the template declaration or template definition interchangeably.
The behavior clang++5 exhibits is definitly a bug.
1) Provided by user Oliv:
[temp.param]/10
The set of default template-arguments available for use is obtained by merging the default arguments from all prior declarations of the template in the same way default function arguments are (
[dcl.fct.default]
). [ Example:template<class T1, class T2 = int> class A; template<class T1 = int, class T2> class A;
is equivalent to
template<class T1 = int, class T2 = int> class A;
— end example ]
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