I costruttori di modelli di classe possono avere un elenco di parametri di modello ridondante in c ++ 20

Aug 21 2020

Per quanto ne so, il codice seguente :

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

è ben formato, anche se il <T>nella dichiarazione del costruttore è ridondante.

Tuttavia, su gcc trunk (ma non su gcc10.2), con -std=c++20questo viene visualizzato un errore:

error: expected unqualified-id before ')' token
    3 |     S<T>();
                 ^

Il codice viene compilato su clang trunk con -std=c++20. È un bug o è un cambiamento radicale in c ++ 20 che deve ancora essere implementato in tutti i compilatori?

Risposte

7 StoryTeller-UnslanderMonica Aug 21 2020 at 05:45

In effetti c'è stato un cambiamento. È documentato nella sezione compatibilità della bozza C ++ 20.

[diff.cpp17.class]

2 Sottoclausole interessate : [class.ctor] e [class.dtor]
Modifica : un simple-template-id non è più valido come dichiaratore-id di un costruttore o distruttore.
Motivazione : rimuovere l'opzione potenzialmente soggetta a errori per la ridondanza.
Effetto sulla funzionalità originale : il codice C ++ 2017 valido potrebbe non essere compilato in questo standard internazionale. Per esempio:

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
};

Nello specifico, la formulazione delta è questa:

n4659 - Bozza standard C ++ 17 - [class.ctor]

1 I costruttori non hanno nomi. In una dichiarazione di un costruttore, il dichiaratore è un dichiaratore di funzione della forma

ptr-declarator ( parameter-declaration-clause ) noexcept-specifier attribute-specifier-seq

dove il ptr-dichiarator consiste esclusivamente di un'espressione id, un attributo-specificatore-seq opzionale e parentesi circostanti opzionali e l'espressione id ha una delle seguenti forme:

  • in una dichiarazione di membro che appartiene alla specifica di membro di una classe ma non è una dichiarazione di amicizia, l'espressione id è il nome di classe inserito della classe che racchiude immediatamente;
  • in una dichiarazione di membro che appartiene alla specifica di membro di un modello di classe ma non è una dichiarazione di amicizia, l'espressione id è un nome di classe che nomina l'istanza corrente del modello di classe che racchiude immediatamente; o

n4861 - Bozza standard C ++ 20 - [class.ctor]

1 Un costruttore viene introdotto da una dichiarazione il cui dichiaratore è un dichiaratore di funzione ([dcl.fct]) della forma

ptr-declarator ( parameter-declaration-clause ) noexcept-specifier attribute-specifier-seq

dove il ptr-dichiarator consiste esclusivamente di un'espressione id, un attributo-specificatore-seq opzionale e parentesi circostanti opzionali e l'espressione id ha una delle seguenti forme:

  • in una dichiarazione di membro che appartiene alla specifica di membro di una classe o di un modello di classe ma non è una dichiarazione di amicizia ([class.friend]), l'espressione id è il nome di classe inserito ([class.pre]) dell'entità che lo racchiude immediatamente o

Come puoi vedere, la formulazione è cambiata. C ++ 20 ora richiede il nome della classe inserito quando si dichiara un costruttore per un modello di classe. S<T>è un semplice ID modello che nomina una specializzazione. All'interno di un modello, il nome della classe inserito è semplicemente S.

Questo fa parte dell'affrontare CWG 2237 .