Is there a good reason why <>
is required when specifying a template class which has defaults for all its template parameters?
e.g.
#include <iostream>
template<typename T = int>
class C {
public:
T obj = 0;
};
int main()
{
C c1; // Error on almost all compilers (see note below)
C<> c2;
std::cout << c1.obj << " " << c2.obj << std::endl;
return 0;
}
An example disadvantage of this is that if you have a class which is already used in various places, and you later refactor it to be a class template with default parameters for its template arguments, then you have to add <>
in all the places which use the class.
Note: it looks like GCC latest HEAD (7.0.1) accepts the syntax without <>
. Earlier versions do not and neither does any version of Clang. Is this a bug in the latest GCC HEAD? Or perhaps C++17's standard now accepts the syntax without <>
and GCC is just ahead here?
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.
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.
A template is a simple yet very powerful tool in C++. The simple idea is to pass data type as a parameter so that we don't need to write the same code for different data types. For example, a software company may need to sort() for different data types.
In C++17, this is well formed:
C c1{};
due to deduction for class templates. We'd synthesize a function for each constructor (and deduction guide) and perform overload resolution:
template <class T=int> C<T> foo();
template <class T=int> C<T> foo(C<T> const&);
template <class T=int> C<T> foo(C<T>&&);
The first one is a viable overload, and the other two are not, so deduction succeeds and the placeholder C
is replaced by the deduced type C<int>
.
However, grammatically, an initializer is required in [dcl.type.class.deduct]:
If a placeholder for a deduced class type appears as a decl-specifier in the decl-specifier-seq of a simple-declaration, the init-declarator of that declaration shall be of the form:
declarator-id attribute-specifier-seqoptinitializer
The placeholder is replaced by the return type of the function selected by overload resolution for class template deduction (13.3.1.8).
But Apparently, this restriction has been lifted in Kona, so C c;
contains no initializer, so it doesn't fit grammatically. This is a gcc bug for allowing this. Although it seems odd to disallow this specifically.C c;
will indeed be well-formed in C++17. I will update the answer once new wording comes out.
Before C++17, the statement was ill-formed simply because C
is not a type. C
and C<>
are not the same thing. There was, and still is no, special consideration for having all defaulted template parameters. Types and class templates are different, and continue to be treated differently.
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