2017-05-04 2 views
0

Kann ich einen Namespace mit einem Klassennamen verketten, indem Sie die Präprozessor-Direktive ## verwenden?Verketten von Namespace und Klassennamen mit C-Präprozessor ## (Doppel-Hash)

Ich habe dieses Beispiel geschrieben zu zeigen, was ich tun mag:

namespace ns { 
class A 
{ 
public: 
    void print(){ std::cout << "A" << std::endl; }; 
}; 
} 

#define PRINT_NS(E) ([](){ ::ns::##E e; e.print(); }()) 

int main() 
{ 
    PRINT_NS(A); 
} 

Es wird folgenden Kompilierungsfehler gibt:

13:30: error: pasting "::" and "A" does not give a valid preprocessing token 
17:3: note: in expansion of macro 'PRINT_NS' 

Es sieht aus wie, was ist, bevor die :: nicht berücksichtigt ##.

+0

Warum sind Sie versuchen, mit '##' zu verketten? Wenn Sie das nicht tun, und tun Sie einfach '' ns :: E' [es funktioniert einfach] (http://ideone.com/2uzmrP). – Cornstalks

+0

Ich habe versucht, '##' in einem Codegenerator zu verwenden, um Präfixe immer auf die gleiche Weise hinzuzufügen, egal ob sie Namespaces oder Teile des Klassennamens, Funktionsnamens usw. sind. – Martin

+0

@Martin In diesem Fall muss der Codegenerator prüfen ob das Präfix mit '::' endet und den entsprechenden Code erzeugen muss. Ich denke, das ist schließlich die einfachere Lösung, als mit Makros in C++ umzugehen. Ist das eine Option für Sie, den Code Generator zu ändern? – Scheff

Antwort

0

In diesem Fall gibt es keine Notwendigkeit, etwas zu kleben, da :: keine Präprozessor-Token Präprozessor ist in der Lage sein wird, E just fine (working example) zu ersetzen:

#define PRINT_NS(E) ([](){ ::ns::E e; e.print(); }()) 

## verwendet werden soll, wenn Sie wollen Teile kleben, die als ein einziges Token, so etwas wie diese behandelt werden anders:

#define PRINT_NS(E) ([](){ ::ns::My_##E e; e.print(); }()) 
Verwandte Themen