2015-10-07 12 views
5

Sto provando a ricavare pubblicamente una classe da un modello che verrà ereditata da una classe base e ottenere l'accesso ai membri protetti. Ma prima che il modello è espansa non ha questi diritti, in modo che non è possibile utilizzare un membro di base come parametro di template:Accesso alla classe base del modello prima dell'espansione del modello derivato da

using Fun = void (*)(); 

class Base { 
protected: 
    // friend class Derived; // ...need this to eliminate complaint 
    static void something(); 
}; 

template<Fun F> 
class Variant : public Base {}; 

class Derived : public Variant<&Base::something> { // `something()` is protected 
public: 
    void somethingElse() { 
     something(); // doesn't complain about this `something()` 
    } 
}; 

int main() {} 

L'po 'strano su questo per me era che friending ha funzionato affatto. Mi chiedevo se potessi "Sneak Derivato dalla porta" mettendo un'eredità virtuale pubblica dalla base prima della Variante:

class Derived : public virtual Base, public Variant<&Base::something> 

quello non ha aiutato.

Domanda: C'è qualche altro trucco per evitare la menzione esplicita di tutte le classi derivate in Base, ma ancora avere accesso per scegliere membri protetti da esso per i parametri del modello?

(Nota:.. Provando questo su un gcc più vecchia, 4.6.3, sembra che anche il friending non aiuta in questo caso Così sembra il supporto per che è un po nuovo)

+3

Correlati: [CWG 372] (http://wg21.cmeerw.net/cwg/issue372) e [CWG 580] (http://wg21.cmeerw.net/cwg/issue580). Sembra che anche le versioni correnti di clang ++ e g ++ non implementino la risoluzione proposta per quest'ultimo difetto. – dyp

+0

@ dyp Sto pensando che probabilmente è "la risposta" o il più vicino possibile. Vuoi farcela? – HostileFork

risposta

1

Stick il offendere l'accesso a una metafunzione. Deriva la classe metafunction dalla base.

template<typename B> 
struct something_variant : public B { 
    typedef Variant< & B::something > type; 
}; 

class Derived : public something_variant<Base>::type { 
    … 

http://coliru.stacked-crooked.com/a/6bca00455bd3daca

Per quanto riguarda CWG 372, il testo critico nella risoluzione è questo:

[A] controllo ccesso di base-prescrittori devono essere differito fino l'intera base-specifier- lista è stata vista

Questo era già accettato in C++ 11, quindi è interessante che il tuo esempio sia respinto. E, plugging il codice di esempio pertinente dallo standard C++ 11 nel recente Clang e GCC dimostra che semplicemente non hanno implementato il differimento. È almeno un po 'non sorprendente, dal momento che l'implementazione richiede una certa struttura di dati per rappresentare una serie di controlli di accesso posticipato ... uno sforzo abbastanza alto per un caso d'angolo.

Problemi correlati