2016-08-03 10 views
1

hier ein minimales Beispiel, das ich tun konnte:Sichtbarkeit Probleme bei der Verwendung von CRTP

template <typename T> 
struct Util 
{ 
    using Type = int; 
}; 

struct A 
{ 
    struct B : public Util<B> { 
     void fun(Type) {} 
    }; 
}; 

template <typename T> 
struct C 
{ 
    struct D : public Util<D> { 
     void fun(Type) {} 
    }; 
}; 

int main() 
{ 
    A::B{}.fun(0); 
    C<int>::D{}.fun(0); 
} 

Der einzige Unterschied zwischen A::B und C::D ist, dass C eine Vorlage.

Struct C::D schlägt mit dem folgenden Fehler zu kompilieren:

test_cpp.cpp:18:18: error: ‘Type’ has not been declared 
     void fun(Type) {} 
        ^~~~ 

Warum tut dies nicht zu kompilieren? Wie mache ich das kompilieren?

Nehmen Sie an, dass Util aus externen Bibliothek ist und ich kann es nicht ändern (es ist boost::iterator_facade, wenn Sie neugierig sind).

Antwort

3

An dieser Stelle:

template <typename T> 
struct C 
{ 
    struct D : public Util<D> { 
     void fun(Type) {} // <-- here 
    }; 
}; 

Der Compiler hat keine Möglichkeit, zu wissen, * dass Type Bedürfnisse von Util<D> ‚s Umfang zu kommen. Es ist das gleiche Problem mit dem Aufruf von Basisklassen-Member-Funktionen, die explizit mit this-> qualifiziert werden müssen, oder sie werden nicht gefunden.

sollten Sie in der Lage sein, dies zu beheben, indem die Art explizit Qualifikation:

void fun(typename Util<D>::Type) {} 

complete snippet on Coliru See.

Der Grund für den Unterschied ist, wie @ etam1024 korrekt in einem Kommentar weist darauf hin, dass in A::B, Type ein nicht-abhängigen Name ist, und in C::D ist es ein abhängiger Name. Eine ähnliche Situation bezüglich der Memberfunktionsqualifizierung der Basisklassenmemberfunktionen this answer finden Sie unter.

* Meiner Meinung nach ist der Compiler kann wissen, wo Type zu suchen, aber die Sprache Regeln sagen, dass es nicht so weit sieht. Anmerkung: Ich könnte spezielle Fälle übersehen, in denen es für den Compiler unmöglich ist, dies abzuleiten, was zu dem allgemeinen Fall führt, der eine vollständige Koalafizierung erfordert.

+0

Danke! Ich würde hinzufügen, dass in "A :: B" der "Typ" ist ein "nicht abhängiger Name" und in "C :: D" ist es ein "abhängiger Name" (es hängt von Vorlage Argument). https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-types – etam1024