2017-09-05 1 views
2

Ich habe folgendes Konstrukt:C++ 11: Variadische Vorlage Abzug Logik

template <class... Args> 
class some_class 
{ 
public: 
    some_class() = default; 
    some_class(Args...) = delete; 
    ~some_class() = default; 
}; 

template<> 
class some_class<void> 
{ 
public: 
    some_class() = default; 
    ~some_class() = default; 
}; 

Der Grund dafür ist, dass ich mag nur die Benutzer erlauben, Objekte zu erstellen, den Standard-Konstruktor verwenden, so zum Beispiel:

some_class<int,float> b; 

funktionieren sollte aber

some_class<int,float> c(1,3.4); 

sollte mir einen Übersetzungsfehler geben.

An einem gewissen Punkt in der Zeit basierend auf void daher muß ich auch Vorlagen erstellen, die Spezialisierung für void:

some_class<void> a; 

Aber Fehler, den ich geschrieben haben:

some_class<> d; 

Und mein Code plötzlich stoppte kompilieren und es gab mir den fehler:

some_class<Args>::some_class(Args ...) [with Args = {}]’ cannot be 
overloaded 
some_class(Args...) = delete; 

So kommt hier die Frage: Ich habe das Gefühl, dass ich falsch liege, dass ich annehme, dass some_class<> auf die void Spezialisierung zurückzuführen sein soll ... Ich weiß einfach nicht warum. Kann jemand bitte erklären warum some_class<> (dh: leere Argumentliste) unterscheidet sich von some_class<void>? (Einige Zeilen aus dem Standard zu tun :))

https://ideone.com/o6u0D6

Antwort

2

void ist eine Art wie jede andere (eine unvollständige Art, um genau zu sein). Dies bedeutet, dass es normalerweise als Vorlagenargument für Typvorlagenparameter verwendet werden kann. Unter Ihrer Klassenvorlage, diese alle perfekt gültig ist, und deutlich, instantiations:

some_class<void> 
some_class<void, void> 
some_class<void, void, void> 
some_class<void, char, void> 

Im ersten Fall wird der Parameter Pack Args hat ein Element: void. Im zweiten Fall hat es zwei Elemente: void und void. Und so weiter.

Dies ist etwas anders als im Fall some_class<>, in diesem Fall hat das Parameterpaket null Elemente. Sie können diese sizeof... mit leicht demonstrieren:

template <class... Pack> 
struct Sizer 
{ 
    static constexpr size_t size = sizeof...(Pack); 
}; 

int main() 
{ 
    std::cout << Sizer<>::size << ' ' << Sizer<void>::size << ' ' << Sizer<void, void>::size << std::endl; 
} 

erhalten Sie folgende Ausgabe:

0 1 2

[Live example]

Ich kann der Standard nicht wirklich, dass eines relevanten Teils zu zitieren. Vielleicht ist das (C++ 11 [temp.variadic] 14.5.3/1):

A template parameter pack is a template parameter that accepts zero or more template arguments. [ Example:

template<class ... Types> struct Tuple { }; 
Tuple<> t0; // Types contains no arguments 
Tuple<int> t1; // Types contains one argument: int 
Tuple<int, float> t2; // Types contains two arguments: int and float 
Tuple<0> error; // error: 0 is not a type 

—end example ]

+0

Danke, Ihre Antwort erklärt perfekt die Situation ...Mein ursprüngliches Problem liegt ein wenig über dieser Ebene, da ich das Parameterpack als Argumenttypen für einige Funktionen in der Klasse verwende (also habe ich 'void' automatisch in etwas übersetzt, das keine Argumente annimmt) und ich habe sogar die Situation, wenn bestimmte Werte sind instantiiert aus dem Argument-Paket, so kam es mir aufgrund dieser Zurückhaltung eigentlich nie in den Sinn, dort '' zu setzen, aber tatsächlich beschreibt diese Antwort die Situation klar. – fritzone