4

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.

Jason
  • 36,170
  • 5
  • 26
  • 60
  • @bobah At the beginning of my question, i have mentioned the [source](https://youtu.be/LMP_sxOaz6g?list=PLpHxZMy35Lo1255K3eSmjd161ra4vSnFT&t=1519) from where this example is. And i don't think they will make this mistake or at least they would tell us about the mistake. Please take a look at the given link? Also, your suggestion of replacing `Rational();` with `Rational();` seems pointless because they both are equivalent according to the given link. – Jason Apr 23 '22 at 09:17
  • @bobah It's not a bug in C++17's compiler. Its valid to use `Rational();` in C++17 and is equivalent to writing `Rational();` according to the given [source](https://youtu.be/LMP_sxOaz6g?list=PLpHxZMy35Lo1255K3eSmjd161ra4vSnFT&t=1519). – Jason Apr 23 '22 at 09:24

2 Answers2

5

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.

super
  • 12,335
  • 2
  • 19
  • 29
1

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.

康桓瑋
  • 33,481
  • 5
  • 40
  • 90
  • So is using `Rational();` valid in all C++ versions? – Jason Apr 23 '22 at 10:16
  • Comment 2 in the link seem to suggest it's invalid, but the error message is bad. Not sure where to look up the DR 2237, [diff.cpp17.class]p2 references. – super Apr 23 '22 at 10:20
  • @康桓瑋 So this means that `Rational();` is valid in C++11, C++14 and C++17 but not in C++20 & onwards, right? – Jason Apr 23 '22 at 10:28
  • @Richard. From [diff.cpp17#class-2](https://eel.is/c++draft/diff.cpp17#class-2): "*Valid C++ 2017 code may fail to compile in this revision of C++.*" – 康桓瑋 Apr 23 '22 at 10:28