class template's constructor declaration doesn't compile for C++20 but compiles for C++17

Viewed 126

I am learning about templates in C++. In particular, i saw here that we can have the following declaration for the constructor:

template<typename T>
struct Rational
{
  Rational<T>();  
};

But the above snippet fails to compile in C++2a and compiles successfully for C++17.

Is this a compiler bug or there is a reason why it doesn't compile for C++2a and C++2b. If there is a reason then what is it. I want to know which clauses(if any) from the standard allow/prevent the following examples to compile. Since i have tested the above example with C++17 and C++20 so i am looking for citation from only these two standard versions.

2 Answers

It is not a bug.

It is the consequence of a change in the standard.

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 revision of C++. 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
};

There is however a bug report, that was initially closed and then reopen with the intention of improving the diagnostics message.

Is this a compiler bug or there is a reason why it doesn't compile for C++2a and C++2b.

Yes, this is a GCC diagnostic bug that has existed since 2020, see PR 97202.

Quoted from Marek Polacek, one of the GCC contributors

This is C++20 DR 2237, disallow simple-template-id in cdtor: see [diff.cpp17.class] p2. Just the diagnostic we give is horrible ;(.

That said, this is the expected behavior with the implementation of DR2237, it's just that diagnostic is a bit bad.

Related