2014-05-24 12 views
7

ich einen Code haben, die wie folgt aussieht:Werden "typename" -Direktiven nicht von Compilern implementiert?

namespace myLibrary 
{ 
    class A 
    { 
    public: 
     struct Nested 
     { 
      ... 
     }; 

     ... 
    }; 
} 

In einigen anderen Teilen des Codes, ich brauche A. zugreifen Da ich lesbaren Code mag, ich wie die using-Direktive auch:

using myLibrary::A; 
... 
A a; 

Nun irgendwann muss ich meine geschachtelten Klasse zuzugreifen auch, so möchte ich, so etwas schreiben:

using myLibrary::A::Nested; 

Offensichtlich ist der Compiler kann nicht wissen, dass dies eine ist verschachtelte Klasse und nicht ein Klassenmitglied, und gibt mir eine Fehlermeldung:

error : using declaration can not refer to class member 

Was kann ich nicht verstehen, warum dies das Problem nicht lösen:

using typename myLibrary::A::Nested; 

Der Compiler noch die genaue gibt mir gleicher Fehler!

Zum Glück, ich habe Alternativen:

// Using a typedef 
typedef myLibrary::A::Nested Nested; 

// Using the new C++11 syntax for type aliasing 
using Nested = myLibrary::A::Nested; 

aber ich würde verstehen, warum die mit Typnamen Richtlinie nicht funktionierte. Tut es nicht, was ich denke, dass es tut? Oder ist es nicht von Compilern implementiert? Wenn es das letztere ist, gibt es einen Grund dafür?

+0

Soweit ich sagen kann, ist es nur für Namespace-Mitglieder, nicht Klassenmitglieder: http://en.cppreference.com/w/cpp/keyword/using – DiscoStu

+0

@DiscoStu: vielleicht, aber in diesem Fall, warum das Schlüsselwort "typename" einführen? Es scheint zu funktionieren mit der Verwendung von: http://en.cppreference.com/w/cpp/language/using_declaration – Eternal

+0

In welchem ​​Kontext versuchen Sie die using-Deklaration zu verwenden? – dyp

Antwort

2

Eine using Deklaration, die sich auf ein Namespacemitglied A bezieht, darf nur im Namespace oder lokalen Bereich angezeigt werden.

A using Erklärung einen Teilnehmer bezieht Nested kann nur an Klassenbereich angezeigt (zusammen mit Elementdeklarationen), in einer Klasse von Nested abgeleitet.In der Tat werden solche using Deklarationen grammatikalisch als Elementdeklarationen betrachtet. Sie werden verwendet, um die Zugriffsqualifizierung anzupassen und (mit typename) Mitgliedern der typabhängigen Basis zu erlauben, ohne Qualifikation verwendet zu werden. Dies sind spezielle Anwendungsfälle, so dass die Member using Deklarationen etwas spezialisiert sind.

Eine verschachtelte Klasse ist ein Mitglied seiner umschließenden Klasse. Sie sollten im Allgemeinen vermeiden, Klassen-Enclosures als Ersatz für Namespaces zu verwenden. Die Metaprogrammierung bietet einige Ausnahmen von der Regel, aber in diesen Fällen würden Sie immer noch keine using Deklarationen verwenden, zumindest nicht im Namespace-Bereich, da Namespaces nicht mit Vorlagen versehen werden können. Eine leere Metaprogrammierungsklasse zu erben ist machbar, aber beachten Sie die Spaghetti.

Die using Direktive ist ein anderes Biest. Es sieht wie using namespace aus und es verbindet einen Namespace mit einem anderen als Fallback-Pfad in der Namenssuche.

3

Es gibt keine "using typename directive". Es gibt using-Direktiven und using-declarations.

Sie verwenden keine using-Direktiven, und sie sind in keinem Fall für die Frage relevant (sie benennen Namespaces und können das Schlüsselwort typeName nicht verwenden).

Wenn mit Klärungen in Klassenvorlagen erscheinen passieren, und zufällig Name abhängige Typen, müssen sie die typename Schlüsselwort wie alles andere, das in einer Vorlage werden passiert und passiert eine abhängige Art zu nennen.

Zum Beispiel:

template <typename A, typename R> 
class Functor : public std::unary_function<A, R> 
{ 
    using typename std::unary_function<A, R>::result_type; 
    using typename std::unary_function<A, R>::argument_type; 
public: 
    result_type operator() (argument_type) {} 
}; 

In Ihrer Situation, die Namespace-Deklaration erscheint nicht ein Teil des Körpers einer Klasse-Vorlage, in der Tat scheint es im Namensraum Umfang zu sein, wobei in diesem Fall 7.3.3[namespace.udecl]/8

A using-declaration for a class member shall be a member-declaration

versucht, einen Teilnehmer zu benennen (egal, ob es sich um eine Art oder eine Funktion oder was auch immer ist) verletzt, wie der Compiler korrekt mit „Fehler: Deklaration verwenden, können nicht in die Klasse Mitglied beziehen“ diagnostiziert

+0

Vielen Dank! Tut mir leid, dass ich es als "Richtlinie" bezeichnet habe. Ich dachte, dass der Unterschied darin bestünde, dass die "using declarations" die im Körper einer Klasse waren und die "using directions" die anderen. – Eternal

Verwandte Themen