2013-03-15 11 views
14

Wenn CRTP innerhalb einer Vorlage verwendet wird (oder allgemein, wenn ein Vorlagenparameter als Basisklassenvorlagenargument übergeben wird), ist es dann nicht möglich, die Mitgliedsvorlagen der Basis in einer using Deklaration zu benennen?Deklaration für typabhängigen Vorlagennamen

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

Es scheint mir, dass dies ein Loch in der Sprache ist, einfach weil die mit Deklaration Grammatik Produktion keine qualifizierte Nummer nicht übernehmen.

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 

Wenn die einzige Regel using-declaration: using typename(opt) qualified-id, würden die einzigen Folgen

  • sein :: conversion-function-id auszuschließen, :: ~ class-name und :: ~ decltype-specifier template-id, die keinen semantischen Sinn machen,
  • ermöglicht :: template-id die bereits verboten ist ausdrücklich 7.3.3/5 und
  • erlaubt das template Schlüsselwort, das bereits ausreichende Spezifikation hat, um das Loch zu patchen.

Ist diese Analyse korrekt?

Da die neue Grammatik zulässig ist, sollte eine Deklaration mit typename eine Klassenvorlage oder Aliasvorlage importieren, und eine ohne typename sollte eine Funktion oder Variablenvorlage in den aktuellen Bereich importieren.

 using typename derived::base::template ct; 
    using derived::base::ft; 

Dies könnte einige zusätzliche Spezifikationen erfordern. Auch der aktuelle Status quo scheint zu sein, dass abhängige Template-Namen immer mehrdeutige Art haben (nicht Template-IDs), so dass es nicht klar ist, dass typename überhaupt zu ct gehört.

+0

Eine interessante Analyse. Ich bin gespannt, wo du das so gebrauchen würdest, dass das identifizierte "Loch" hemmen würde. I.e. Was ist eine Anwendung in der realen Welt, in der dies die Blockade ist, die dazu führt, dass Sie zurücktreten und die Architektur des Programms neu überdenken müssen? – WhozCraig

+0

@WhozCraig Dies wird jedes Mal angezeigt, wenn Sie CRTP aus einer Vorlage verwenden. Die Basisklasse bietet eine Schnittstelle, für die Sie bei jeder Verwendung 'this -> * template' oder' base :: template' sagen müssen. – Potatoswatter

+0

Ok, ich denke, ich verstehe es. Dieser spezielle Fall bezieht sich auf die Verwendung einer Klausel, die das Leben erleichtert, aber anscheinend nicht erlaubt ist. Gutes Beispiel. Vielen Dank. – WhozCraig

Antwort

2

Folgende funktioniert gut mit C++ 11:

#include <iostream> 

template< typename d > 
struct base { 
    template<typename> 
    struct ct {}; 

    template<typename> 
    void ft() {std::cerr << "cheesecake" << std::endl;} 
}; 

template< typename x > 
struct derived : base< derived<x> > { 
    template<typename X> 
    using ct = typename derived::base::template ct<X>; // new in C++11 
    using derived::base::ft; 
}; 

int main() 
{ 
    derived<int>::ct<float> c; 
    derived<int> a; 
    a.ft<int>(); 
} 

Wenn das nicht das, was Sie gewünscht wird, können Sie bitte ein Beispiel geben, wie Sie ct und ft verwenden wollen würde?

+1

Ja, der Template-Alias ​​funktioniert, obwohl es eine erneute Deklaration der Template-Signatur erfordert, die die Trennung der Probleme etwas durchbricht. Die Funktion 'using' Deklaration funktioniert nicht im Rahmen von' derived'. Perfekte Weiterleitung würde funktionieren. Aber diese verwenden keine Deklarationen. Die hinzugefügte Fußarbeit vereitelt den Zweck einer 'using'-Deklaration, die darin besteht, eine Deklaration von einem Bereich in einen verwandten zu importieren * ohne * etwas neu zu deklarieren. Wie auch immer ... füge die perfekte Weiterleitung hinzu und ich sollte das akzeptieren. – Potatoswatter

Verwandte Themen