2010-10-26 13 views
5

Se creo un membro puntatore-base, è possibile convertirlo in un membro puntatore-derivato in genere, ma non quando viene utilizzato all'interno di un modello come Buzz in basso, dove il primo argomento del modello influenza il secondo. Sto combattendo i bug del compilatore o lo standard impone davvero che questo non funzioni?Perché non posso eseguire il downcast del puntatore ai membri negli argomenti del modello?

struct Foo 
{ 
    int x; 
}; 

struct Bar : public Foo 
{ 
}; 

template<class T, int T::* z> 
struct Buzz 
{ 
}; 

static int Bar::* const workaround = &Foo::x; 

int main() 
{ 
    // This works. Downcasting of pointer to members in general is fine. 
    int Bar::* y = &Foo::x; 

    // But this doesn't, at least in G++ 4.2 or Sun C++ 5.9. Why not? 
    // Error: could not convert template argument '&Foo::x' to 'int Bar::*' 
    Buzz<Bar, &Foo::x> test; 

    // Sun C++ 5.9 accepts this but G++ doesn't because '&' can't appear in 
    // a constant expression 
    Buzz<Bar, static_cast<int Bar::*>(&Foo::x)> test; 

    // Sun C++ 5.9 accepts this as well, but G++ complains "workaround cannot 
    // appear in a constant expression" 
    Buzz<Bar, workaround> test; 

    return 0; 
} 

risposta

5

Semplicemente non consentito. Secondo §14.3.2/5:

Le seguenti conversioni vengono eseguite su ogni espressione utilizzata come argomento modello non di tipo. Se un argomento modello non di tipo non può essere convertito nel tipo del parametro modello corrispondente, allora il programma è mal formato.
- per un parametro di modello non di tipo di tipo integrale o di enumerazione, vengono applicate le promozioni integrali (4.5) e le conversioni integrali (4.7).
- per un parametro modello non di tipo di puntatore di tipo su oggetto, le conversioni di qualifica (4.4) e la conversione da matrice a puntatore (4.2) vengono applicate. - Per un parametro modello non di tipo di riferimento del tipo all'oggetto, non si applicano conversioni. Il tipo cui fa riferimento il riferimento può essere più qualificato cv del tipo (altrimenti identico) dell'argomento modello. Il parametro template è associato direttamente all'argomento template, che deve essere un lvalue.
- Per un parametro modello non tipografico di tipo puntatore a funzione, viene applicata solo la conversione da funzione a puntatore (4.3). Se l'argomento template rappresenta una serie di funzioni sovraccaricate (o un puntatore a tale), la funzione di corrispondenza viene selezionata dall'insieme (13.4).
- Per un parametro modello non di tipo di riferimento del tipo alla funzione, non si applicano conversioni. Se l'argomento template rappresenta un insieme di funzioni sovraccariche, la funzione di corrispondenza viene selezionata dall'insieme (13.4).
- Per un parametro modello non di tipo del puntatore del tipo alla funzione membro, non si applicano conversioni. Se l'argomento template rappresenta un insieme di funzioni membro sovraccaricate, la funzione membro corrispondente viene selezionata dall'insieme (13.4).
- Per un parametro modello non di tipo del puntatore di tipo al membro dati, vengono applicate le conversioni di qualificazione (4.4).

Ho sottolineato la conversione del puntatore ai dati membri. Si noti che la conversione (§4.11/2) non è elencata. In C++ 0x, rimane lo stesso a questo proposito.

+0

Decisamente giusto, ma qualche idea del perché non è permesso? Sembra arbitrario. –

+1

@Joseph: Anch'io ho pensato che fosse così, motivo per cui ho anche controllato C++ 0x. (Hanno rimosso molte decisioni apparentemente arbitrarie, come nessun parametro predefinito per i modelli di funzione.) Nessuno ha trovato un uso per questo e quindi non è davvero cambiato/quindi semplicemente non è stato spinto per (è più facile aggiungere un well- funzionalità testata piuttosto che deprecare una funzionalità interrotta), o c'è qualche motivo fondamentale che non riesco a vedere. – GManNickG

Problemi correlati