2016-08-22 4 views
1

Ich bin auf ein kleines Problem mit ein wenig Code gestoßen, den ich mache, während ich C++ 11/14 lerne. Im Grunde habe ich eine Debugging-Klasse, die ich alle Nachricht drucken soll. Die meisten Debugging/Logging-Klassen haben verschiedene Arten von Log-Ebenen, aber ich möchte ein Flag für jede Nachricht verwenden, die ich habe.Doppelte partielle Template-Spezialisierung für eine Klasse

Dafür habe ich ein wenig Enum, wo ich meine Fahnen und ihre Werte definieren:

enum DebugFlag { 
    Flag1 = 0, 
    Flag2 = 1, 
    Flag3 = 2 
}; 

Aditionally, habe ich eine Debug-Klasse, die ich habe es geschafft, für Flag-Typen zu spezialisieren und es funktioniert ziemlich gut .

template<DebugFlag T> 
class Debug { 
public: 
    template <typename U> 
    static void print(U &&arg) {} 
}; 

template <> 
class Debug<static_cast<DebugFlag>(1)> { 
public: 
    static void print(std::string &&message) { 
     std::cerr<<message<<"\n"; 
    } 

    static void print(std::ostream &message) { 
     std::cerr<<DebugStream()().str()<<"\n"; 
     DebugStream()().str(""); 
     DebugStream()().clear(); 
    } 

    static void print(std::string &message) { 
     std::cerr<<message<<"\n"; 
    } 
}; 

diese Klasse aufrufen, verwende ich ein Aufruf wie:

Debug<Flag1>::print("Message\n"); // should not do anything with Flag1 compiled to 0 value 
Debug<Flag2>::print("Message\n"); // should work 

Nun wollte ich diese Klasse erweitern auch bool Werte zu nehmen, so wie diese Anrufe funktionieren:

Debug< Flag2<2 >::print("Message\n"); // should not do anything with Flag1 compiled to 2 value 
Debug< Flag2<1 >::print("Message\n"); // should work 

Das Problem ist, ich brauche eine zweite teilweise Spezialisierung für meine Debug-Klasse, das ist bool, und ich kann nicht genau herausfinden, was die Syntax dafür ist. Dies ist die nächste, die ich dazu gekommen bin, aber immer noch nicht herausfinden kann, was ich falsch mache, oder wenn es möglich ist, ohne eine sekundäre Klasse zu machen und ändern, wie ich meinen Anruf aussehen soll: http://cpp.sh/6yemn

Antwort

2

Ich verstehe nicht genau, wie Sie Ihre Klasse verwenden möchten, aber hier ist etwas, das funktioniert.

template <typename T, T v = T()> 
class Debug {}; 

template <> 
class Debug<Flag, Flag2> { 
public: 
    void f() { std::cout<<"This is good\n"; } 
}; 

template <> 
class Debug<bool, true> { 
public: 
    void f() { std::cout<<"This is good too\n"; } 
}; 

Das Problem ist, dass Sie den Typ angeben müssen: ob Sie den Wert eines bool oder eine Flag, und dann verwenden möchten. Sie können die Klasse instanziiert wie so:

Debug<bool, true> trueDebug; 
Debug<Flag, Flag2> flag2Debug; 

Andere Instanzen nicht die f Funktion haben, wenn Sie eine Spezialisierung hinzufügen. Zum Beispiel:

template <Flag v> 
class Debug<Flag, v> { 
public: 
    void f() { std::cout<<"This is bad\n"; } 
}; 

Live example

+0

Hallo, danke für die Antwort. Vielleicht habe ich das Beispiel mit dem 'Debug ', 'int' und' Flag' Beispiel verwechselt. In Wirklichkeit sind alle meine Aufrufe entweder 'Debug ', 'Debug ,' oder 'Debug '. Was ich von Ihrer Antwort gesammelt habe, ist, dass es keine Möglichkeit für mich gibt, 2 partielle Implementierungen von 2 verschiedenen Typen (dh Boolean True und alle Flags, die gleich 1 sind) mit 1 Template-Parameter (wie in dem Code, den ich in der Frage, nicht der Link, der funktioniert). –

+0

C++ 17 würde erlauben, den ersten Parameter loszuwerden, also die erwartete Syntax zu haben. (mit 'Vorlage Klasse Debug;') – Jarod42

+0

Für meine Neugier, etwas dagegen, mir zu sagen, was Sie suchen oder einen Link für den C++ 17 Entwurf zur Verfügung stellen? Ich habe wirklich ein paar Stunden nach diesem Problem gesucht, weil es irgendwie lösbar schien. Der traurige Teil ist, dass ich das sehr leicht mit '# defines' hätte machen können, aber ich versuche, sie jetzt komplett in C++ für const/constexpr und Templates zu vermeiden, aber es ist nicht immer so einfach . –

Verwandte Themen