As far as I'm aware, the following code:
template<typename T>
struct S {
S<T>();
};
is well-formed, even though the <T>
in the declaration of the constructor is redundant.
However, on gcc trunk (but not on gcc10.2), with -std=c++20
this gives an error:
error: expected unqualified-id before ')' token
3 | S<T>();
^
The code compiles on clang trunk with -std=c++20
. Is this a bug, or is this a breaking change in c++20 that is yet to be implemented in all compilers?
Templates can be template parameters. In this case, they are called template parameters. The container adaptors std::stack, std::queue, and std::priority_queue use per default a std::deque to hold their arguments, but you can use a different container. Their usage is straightforward.
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.
Why we use :: template-template parameter? Explanation: It is used to adapt a policy into binary ones.
There was a change, in fact. It's documented in the compatibility section of the C++20 draft.
[diff.cpp17.class]
2 Affected subclauses: [class.ctor] and [class.dtor]
Change: A simple-template-id is no longer valid as the declarator-id of a constructor or destructor.
Rationale: Remove potentially error-prone option for redundancy.
Effect on original feature: Valid C++ 2017 code may fail to compile in this International Standard. For example:template<class T> struct A { A<T>(); // error: simple-template-id not allowed for constructor A(int); // OK, injected-class-name used ~A<T>(); // error: simple-template-id not allowed for destructor };
Specifically, the wording delta is this:
n4659 - C++17 standard draft - [class.ctor]
1 Constructors do not have names. In a declaration of a constructor, the declarator is a function declarator of the form
ptr-declarator ( parameter-declaration-clause ) noexcept-specifier attribute-specifier-seq
where the ptr-declarator consists solely of an id-expression, an optional attribute-specifier-seq, and optional surrounding parentheses, and the id-expression has one of the following forms:
- in a member-declaration that belongs to the member-specification of a class but is not a friend declaration, the id-expression is the injected-class-name of the immediately-enclosing class;
- in a member-declaration that belongs to the member-specification of a class template but is not a friend declaration, the id-expression is a class-name that names the current instantiation of the immediately-enclosing class template; or
n4861 - C++20 standard draft - [class.ctor]
1 A constructor is introduced by a declaration whose declarator is a function declarator ([dcl.fct]) of the form
ptr-declarator ( parameter-declaration-clause ) noexcept-specifier attribute-specifier-seq
where the ptr-declarator consists solely of an id-expression, an optional attribute-specifier-seq, and optional surrounding parentheses, and the id-expression has one of the following forms:
- in a member-declaration that belongs to the member-specification of a class or class template but is not a friend declaration ([class.friend]), the id-expression is the injected-class-name ([class.pre]) of the immediately-enclosing entity or
As you can see, the wording changed. C++20 now requires the injected class name when declaring a constructor for a class template. S<T>
is a simple template id that names a specialization. Inside a template, the injected class name is simply S
.
This is part of addressing CWG 2237.
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