Warum nicht den Template-Parameter aus dem Konstruktor ableiten?
meine Frage heute ist ganz einfach: warum kann nicht der compiler template-Parameter aus der Klasse Konstruktoren, ähnlich wie Sie es tun können Funktion Parameter? Zum Beispiel, warum nicht Sie den folgenden code gültig:
template<typename obj>
class Variable {
obj data;
public: Variable(obj d)
{
data = d;
}
};
int main()
{
int num = 2;
Variable var(num); //would be equivalent to Variable<int> var(num),
return 0; //but actually a compile error
}
Wie gesagt, ich verstehe, dass dies nicht gilt, so meine Frage ist warum ist es nicht? Würde, so dass daraus keine größeren syntaktischen Löcher? Gibt es eine Instanz wo man würde nicht wollen, dass diese Funktionalität (wo Herleitung eines geben würde, die Probleme verursachen)? Ich versuche nur zu verstehen, die Logik dahinter, so dass die Vorlage Ableitung für Funktionen, die noch nicht mit entsprechend konstruierten Klassen.
InformationsquelleAutor der Frage GRB | 2009-06-11
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich denke, es ist nicht gültig, da der Konstruktor ist nicht immer der einzige Punkt, der Eintrag der Klasse (ich bin sprechen über copy-Konstruktor und operator=). Also angenommen, Sie sind mit Ihrer Klasse wie folgt aus :
Ich bin nicht sicher, ob es wäre so offensichtlich für den parser, um zu wissen, welches template-Typ ist der MyClass Uhr;
Nicht sicher, ob das, was ich sagte, Sinn machen, aber fühlen Sie sich frei, um einige Kommentare, das ist eine interessante Frage.
C++ 17
Es wird angenommen, dass C++17 über den Typ mit dem Abzug von Konstruktor-Argumenten.
Beispiele:
Akzeptiert Papier.
InformationsquelleAutor der Antwort Drahakar
Können Sie nicht tun, was Sie Fragen für die Gründe, warum andere Leute angesprochen haben, aber Sie können dies tun:
die für alle Absichten und Zwecke ist die gleiche Sache, die Sie Fragen, für.
Wenn Sie Liebe Kapselung können Sie machen make_variable eine statische member-Funktion. Das ist es, was die Leute rufen namens constructor. Damit es nicht nur tun, was Sie wollen, aber es ist fast genannt, was Sie wollen: der compiler ist infering die template-parameter von der (namens) - Konstruktor.
NB: jeder vernünftige compiler optimieren wird, entfernt das temporäre Objekt, wenn Sie so etwas schreiben
InformationsquelleAutor der Antwort Lionel
In der aufgeklärten Zeitalter 2016 mit zwei neuen standards unter unseren Gürtel, da wurde diese Frage gestellt und eine neue gleich um die Ecke, die entscheidend zu wissen ist, dass Compiler unterstützt C++17 standard wird kompilieren Sie Ihren code wie Sie ist.
Template-argument Abzug für Klassen-templates in C++17
Hier (mit freundlicher Genehmigung von ein Bearbeiten von Olzhas Zhumabek der die akzeptierte Antwort) ist das Papier detailliert die relevanten Veränderungen der standard.
Fragen von anderen Antworten
Die aktuellen top-bewerteten Antwort
Diese Antwort weist darauf hin, dass "copy-Konstruktor und
operator=
" würden nicht wissen, die richtige template-Spezialisierungen.Dies ist Unsinn, da die standard-copy-Konstruktor und
operator=
existieren nur für eine bekannt template-type:Hier, wie ich bereits in den Kommentaren, es ist keinen Grund für
MyClass *pm
eine rechtliche Erklärung mit oder ohne die neue form der Inferenz:MyClass
ist nicht eine Art (es ist ein template), so dass es nicht sinnvoll ist, zu deklarieren, die einen Zeiger vom TypMyClass
. Hier ist eine mögliche Lösung des Beispiel:Hier
pm
ist bereits der richtige Typ, und so die Folgerung ist trivial. Darüber hinaus ist es unmöglich, versehentlich mix Typen beim aufrufen der copy-Konstruktor:Hier
pm
wird ein Zeiger auf eine Kopie desm
. HierMyClass
wird, kopieren-hergestellt ausm
—das ist der TypMyClass<string>
(und nicht der nicht vorhandenen TypMyClass
). So, an der Stelle, wopm
's Art hergeleitet werden, es ist genug Informationen, um zu wissen, dass die template-Typ derm
und deshalb die template-Typ derpm
iststring
.Darüber hinaus die folgenden immer heben Sie einen compile-Fehler:
Dies ist, weil die Deklaration des copy-Konstruktors ist nicht Vorlagen:
Hier, den copy-Konstruktor-argument ist template-Typ entspricht der template-Typ der Klasse insgesamt; D. H., wenn
MyClass<string>
instanziiert wird,MyClass<string>::MyClass(const MyClass<string>&);
instanziiert wird, und wennMyClass<int>
instanziiert wird,MyClass<int>::MyClass(const MyClass<int>&);
instanziiert wird. Es sei denn, es ist explizit angegeben oder eine templatized-Konstruktor deklariert ist, gibt es keinen Grund für den compiler zu instanziierenMyClass<int>::MyClass(const MyClass<string>&);
das wäre natürlich unangemessen.Die Antwort von Cătălin Pitiș
Pitiș gibt ein Beispiel der Aufzucht
Variable<int>
undVariable<double>
sagt dann:Wie bereits im vorigen Beispiel
Variable
selbst ist nicht einen Typ-Namen, obwohl die neue Funktion macht es Aussehen wie ein syntaktisch.Pitiș dann fragt, was passieren würde, wenn kein Konstruktor angegeben ist, damit die entsprechende Inferenz. Die Antwort ist, dass kein Rückschluss zulässig ist, weil die Ableitung ausgelöst durch die Konstruktor-Aufruf. Ohne eine Konstruktor-Aufruf, es ist kein Rückschluss.
Dies ist ähnlich zu Fragen, welche version von
foo
wird gefolgert hier:Die Antwort ist, dass dieser code illegal ist, für den angegebenen Grund.
MSalter Antwort
Dies ist, soweit ich das beurteilen kann, die einzige Antwort, um eine legitime Besorgnis über die geplante Funktion.
Ist ein Beispiel:
Die entscheidende Frage ist, weiß der compiler wählen Sie die Typ abgeleitet Konstruktor hier oder die kopieren Konstruktor?
Versucht den code aus, können wir sehen, dass der copy-Konstruktor ausgewählt ist. Erweitern Sie das Beispiel:
Ich bin nicht sicher, wie der Vorschlag und die neue version des Standards anzugeben; es erscheint werden bestimmt durch "Abzug guides", die ein neues bit von standardese, dass ich noch nicht verstehen.
Ich bin auch nicht sicher, warum die
var4
Abzug ist rechtswidrig; der compiler-Fehler von g++ scheint zu zeigen, dass die Aussage wird analysiert, wie eine Funktionsdeklaration.InformationsquelleAutor der Antwort Kyle Strand
Fehlt noch: Es macht den folgenden code ziemlich zweideutig:
InformationsquelleAutor der Antwort MSalters
Angenommen, dass der compiler unterstützt, was Sie gefragt haben. Dann ist dieser code gültig ist:
Nun, ich habe den gleichen Typ name (Variable) in den code für zwei verschiedene Arten (Variable und Variable). Aus meiner subjektiven Sicht, es wirkt sich auf die Lesbarkeit des Codes ziemlich viel. Mit demselben Typ-Namen für zwei verschiedene Arten im gleichen Namensraum sieht irreführend für mich.
Späteren update:
Eine andere Sache zu prüfen: teilweise (oder vollständige) Vorlage Spezialisierung.
Was ist, wenn ich spezialisieren Variabel und bieten keinen Konstruktor, wie Sie es erwarten?
Also ich hätte:
Dann habe ich den code:
Was sollte der compiler tun? Verwenden Sie die generische Klasse Variablen-definition ableiten, dass es Variabel ist, dann entdecken Sie, dass die Variable nicht einem parameter-Konstruktor?
InformationsquelleAutor der Antwort Cătălin Pitiș
C++03 und C++11 standard nicht für Vorlage-argument Abzug von den übergebenen Parametern, um die constuructor.
Aber es ist ein Vorschlag für "Template-parameter Abzug für Konstrukteure" so können Sie bekommen, was Sie fordern bald. Edit: in der Tat, diese Funktion wurde bestätigt für C++17.
Finden Sie unter: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3602.html und http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0091r0.html
InformationsquelleAutor der Antwort ChetS
Viele Klassen verlassen Sie sich nicht auf Konstruktor-Parameter. Es gibt nur wenige Klassen, die nur einen Konstruktor und die Parametrisierung basiert auf dieser Konstruktor wird der Typ(s).
Wenn Sie wirklich brauchen, Vorlage Inferenz, verwenden Sie eine Hilfsfunktion:
InformationsquelleAutor der Antwort rlbond
Abzug der Arten ist begrenzt, über die template-Funktionen in aktuellen C++, aber es ist längst klar, dass Typ-Abzug in anderen Kontexten sehr nützlich sein würde. Also C++0x ist
auto
.Während genauwas Sie vorschlagen, ist nicht möglich, in C++0x die folgende Abbildung zeigt, können Sie bekommen ziemlich nahe:
InformationsquelleAutor der Antwort James Hopkin
Du Recht, der compiler könnte leicht erraten, aber es ist nicht in der standard-oder der C++0x-soweit ich weiß, also müssen Sie warten, mindestens weitere 10 Jahre (ISO-Normen fest drehen, um rate) vor der compiller Anbieter dieses feature hinzufügen
InformationsquelleAutor der Antwort Robert Gould
Schauen wir uns das problem mit Referenz zu einer Klasse jeder sollte vertraut - std::vector.
Erstens, eine sehr häufige Verwendung von Vektor zu verwenden, der Konstruktor, der keine Parameter:
In diesem Fall offensichtlich keine Ableitung durchgeführt werden kann.
Einer zweiten gemeinsamen Nutzung ist die Erstellung eines pre-dimensionierten Vektor:
Hier, wenn die Inferenz verwendet wurden:
erhält man einen Vektor von int-Werte, keine Zeichenfolgen, und vermutlich ist es nicht Größe!
Schließlich betrachten Konstruktoren, die mehrere Parameter übernehmen - mit "Inferenz":
Welche parameter sollte verwendet werden, für eine Schlussfolgerung? Wir brauchen etwas so zu sagen, der compiler, dass es sein sollte, die zweite.
Mit all diesen Problemen für eine Klasse so einfach, wie Vektor -, es ist leicht zu sehen, warum der Inferenz nicht genutzt.
InformationsquelleAutor der Antwort
Macht das Tor, eine Vorlage, die Variable kann nur eine form aber verschiedene ctors:
Sehen? Wir können nicht mehrere Variable::Mitglieder-Daten.
InformationsquelleAutor der Antwort Nick Dandoulakis
Sehen Die C++ - Template-Argument-Abzug für mehr info auf das.
InformationsquelleAutor der Antwort Igor Krivokon