Quando CRTP viene utilizzato all'interno di un modello, (o in genere quando un parametro modello viene passato come argomento del modello di classe base), è impossibile denominare i modelli membro della base in una dichiarazione using
?Utilizzo della dichiarazione per il nome del modello dipendente dal tipo
template< typename d >
struct base {
template<typename>
struct ct {};
template<typename>
void ft() {}
};
template< typename x >
struct derived : base< derived<x> > {
using derived::base::template ct; // doesn't work
using derived::base::ft; // works but can't be used in a template-id
};
Mi sembra che questo sia un buco nella lingua, semplicemente perché il utilizzando-dichiarazione di produzione grammatica non incorpora un qualificata id.
using-declaration:
using typename(opt) nested-name-specifier unqualified-id ; // have this
using :: unqualified-id ;
unqualified-id:
identifier
operator-function-id
conversion-function-id
literal-operator-id
~ class-name
~ decltype-specifier
template-id
qualified-id:
nested-name-specifier template(opt) unqualified-id // want this
:: identifier
:: operator-function-id
:: literal-operator-id
:: template-id
Se l'unica regola erano using-declaration: using typename(opt) qualified-id
, le uniche conseguenze sarebbero
- escludere
:: conversion-function-id
,:: ~ class-name
, e:: ~ decltype-specifier template-id
che non hanno alcun senso semantico, - permettendo
:: template-id
che è già espressamente vietato dalla 7.3.3/5 e - che consente la parola chiave
template
che ha già specifiche sufficienti per correggere il buco.
Questa analisi è corretta?
Dato che la nuova grammatica era consentita, forse una dichiarazione con typename
dovrebbe importare un modello di classe o un modello di alias e uno senza typename
dovrebbe importare una funzione o un modello di variabile nell'ambito corrente.
using typename derived::base::template ct;
using derived::base::ft;
Ciò potrebbe richiedere alcune specifiche aggiuntive. Inoltre, lo status quo attuale sembra essere che i nomi dei modelli dipendenti abbiano sempre un tipo ambiguo (non id template), quindi non è chiaro che typename
appartiene a ct
.
Un'analisi interessante. Sono curioso di sapere dove useresti * questo in modo tale che il "buco" identificato sarebbe inibitore. Cioè cos'è un'applicazione del mondo reale in cui questo è il posto di blocco che ti costringe a fare un passo indietro e a riconsiderare l'architettura del programma? – WhozCraig
@WhozCraig Arriva ogni volta che usi CRTP da un modello. La classe base fornisce un'interfaccia per la quale devi dire 'questo -> * template' o' base :: template' ad ogni utilizzo. – Potatoswatter
Ok, penso di averlo capito. Questo caso particolare riguarda l'utilizzo di quella con una clausola 'using' per semplificare la vita, ma non sembra consentita. Buon esempio. Grazie. – WhozCraig