2012-10-06 5 views
7

Ich finde etwas nervig in C++ und ich weiß nicht, ob es einen Trick gibt, um dies ohne Overhead zu vermeiden. Das Problem ist folgendes:Warum müssen wir <> für eine Vorlagenklasse mit Standardparametern angeben?

Für eine Template-Funktion, können wir haben:

// Function declaration/definition 
template<bool Option = false> void myFunction() 
{ 
    std::cout<<"Option = "<<Option<<std::endl; 
} 

// Then I can use : 
myFunction<false>(); 
myFunction<true>(); 
myFunction(); // <- NO PROBLEM HERE 

Jetzt für eine Template-Klasse:

// Class definition/declaration 
template<bool Option = false> class MyClass 
{ 
}; 

// Then I can use : 
myClass<false> x; 
myClass<true> y; 
myClass z; // <- PROBLEM HERE : only "MyClass<> z;" will compile ! 

Warum der Grund für dieses Verhalten ist? Gibt es einen Trick, um das zu vermeiden? Für eine Klasse mit Optionnal Parameter als Template übergeben, finde ich dies für den Endverbraucher nicht praktisch: er in der Lage sein sollte, die Standardimplementierung als No-Templat-Klasse zu verwenden ...

+0

„* Gibt es einen Trick, das zu vermeiden? *“ Nein, es sei denn, Sie eine neue Art betrachten zu schaffen (mit einem anderen Namen), die öffentlich von ihr erbt und leitet alle Konstrukteure. – ildjarn

+4

Oder benutzen Sie einfach eine typedef statt Vererbung: 'typedef myClass myClassDef;' –

+0

@Remy: Oh ja, oder dass. :-P Ich glaube, mein Gehirn ist für den Tag getan. – ildjarn

Antwort

8

Warum ist der Grund dieses Verhalten?

Es ist, weil Funktionen überladen werden können, und Typen können nicht.

Wenn Sie einen Funktionsaufruf schreiben, füllt der Compiler eine Überladungsmenge aller Funktionen auf, die er mit diesem Namen finden kann, und ermittelt dann, welche mit den übergebenen Argumenten übereinstimmen. Damit dies mit Funktionsvorlagen sauber funktioniert, können die Argumenttypen für die Vorlage aus den Parametern abgeleitet werden. Da Typ-Parameter-Inferenz im Allgemeinen erlaubt ist, funktioniert es in Ihrem Fall auch dann, wenn der Parameter stattdessen voreingestellt ist.

Die Typen sind jedoch nicht überladen. Während sich myFunction<true>() und myFunction<false>() beide auf das Ausmaß beziehen, in dem sie an dem gleichen Überlastungssatz teilnehmen werden, sind myClass<true> und myClass<false> separate und nicht verwandte Typen. Ohne Überladen von Typnamen ist es nicht sinnvoll, einen Sonderfall hinzuzufügen, um eine vollständig spezialisierte Vorlagenklasse implizit zu benennen. Die Parameter können niemals abgeleitet werden, so dass es nur für den Fall, in dem sie alle voreingestellt sind, zu einer speziellen Syntax kommen würde.

Gibt es einen Trick, um das zu vermeiden?

Im Allgemeinen, wenn Sie Template-Argument Abzug für Template-Klassen erhalten möchten, können Sie eine Vorlage Funktion Wrapper liefern (dies funktioniert am besten mit C++ 11 Auto)

template <bool Option=false> class MyClass {}; 
template <bool Option=false> MyClass<Option> make_my_class() { 
    return MyClass<Option>(); 
} 
// ... 
auto z = make_my_class(); 

Ansonsten, denke ich mit typedef (wie Remy's Kommentar) ist die beste Option.

3

myClass ist eine Klassenvorlage, keine Klasse. Nur myClass<true> oder myClass<> ist eine Klasse.

Ebenso ist myFunction eine Funktionsvorlage, keine Funktion. Wenn Sie jedoch eine TED-Funktion ausführen, können die Vorlagenargumente für Sie abgeleitet werden, und Sie müssen nicht explizit Template-Argumente angeben, wenn sie abgeleitet werden können. Somit ist der Funktionsaufruf-Ausdruck myFunction(); gültig und das erste Argument wird als false abgeleitet. Es ist nur so, dass die Deduktion dank des Standardarguments erfolgt, anstatt mit Funktionsargumenten übereinzustimmen.

Verwandte Themen