Warum nicht den Vorlagenparameter vom Konstruktor ableiten?


102

Meine heutige Frage ist ziemlich einfach: Warum kann der Compiler keine Vorlagenparameter aus Klassenkonstruktoren ableiten, so wie es aus Funktionsparametern möglich ist? Warum konnte beispielsweise der folgende Code nicht gültig sein:

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 gültig ist. Meine Frage ist also, warum nicht? Würde dies größere syntaktische Lücken schaffen? Gibt es eine Instanz, in der man diese Funktionalität nicht möchte (wo das Ableiten eines Typs Probleme verursachen würde)? Ich versuche nur, die Logik zu verstehen, die dahinter steckt, Template-Inferenz für Funktionen zuzulassen, aber nicht für entsprechend konstruierte Klassen.


Ich würde jemanden einladen (ich mache es, gerade nicht), Drahakar und Pitis Antwort (zumindest) als gute Gegenbeispiele zusammenzustellen, warum es nicht funktionieren kann
jpinto3912

2
Beachten Sie auch, dass dies leicht übertemplate<class T> Variable<T> make_Variable(T&& p) {return Variable<T>(std::forward<T>(p));}
Mooing Duck

3
Sie können sozusagen das bekommen, was Sie wollen var = Variable <decltype (n)> (n);
QuentinUK

18
C ++ 17 wird dies ermöglichen! Dieser Vorschlag wurde angenommen: open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0091r0.html
underscore_d

1
@underscore_d Ausgezeichnet! Über die Zeit! Es fühlte sich für mich natürlich an, wie es funktionieren sollte, und die Quelle der Irritation, die es nicht tat.
Amdn

Antworten:


46

Ich denke, es ist nicht gültig, weil der Konstruktor nicht immer der einzige Einstiegspunkt der Klasse ist (ich spreche von Kopierkonstruktor und Operator =). Angenommen, Sie verwenden Ihre Klasse folgendermaßen:

MyClass m(string s);
MyClass *pm;
*pm = m;

Ich bin mir nicht sicher, ob es für den Parser so offensichtlich wäre, zu wissen, welcher Vorlagentyp die MyClass pm ist.

Ich bin mir nicht sicher, ob das, was ich gesagt habe, Sinn macht, aber ich kann gerne einen Kommentar hinzufügen. Das ist eine interessante Frage.

C ++ 17

Es wird akzeptiert, dass C ++ 17 einen Typabzug von Konstruktorargumenten hat.

Beispiele:

std::pair p(2, 4.5);
std::tuple t(4, 3, 2.5);

Akzeptiertes Papier .


8
Dies ist eigentlich ein großartiger Punkt, an den ich nie gedacht habe. Ich sehe keinen Weg daran vorbei, dass der Zeiger typspezifisch sein müsste (dh MyClass <string> * pm). Wenn dies der Fall ist, würden Sie sich am Ende nur ersparen, den Typ bei der Instanziierung anzugeben. ein paar bloße Zeichen zusätzlicher Arbeit (und nur, wenn das Objekt auf dem Stapel erstellt wird, nicht auf dem Heap, wie oben beschrieben). Ich hatte immer den Verdacht, dass Klassenschlussfolgerungen eine syntaktische Dose Würmer öffnen könnten, und ich denke, das könnte es sein.
GRB

2
Ich verstehe nicht ganz, wie das Zulassen der Inferenz von Vorlagenparametern von Konstruktoren das Zulassen nicht spezialisierter Deklarationen ohne Konstruktoraufrufe erfordern würde , wie in Ihrer zweiten Zeile. Das heißt, MyClass *pmhier wäre aus demselben Grund ungültig, aus dem eine deklarierte Funktion template <typename T> void foo();nicht ohne explizite Spezialisierung aufgerufen werden kann.
Kyle Strand

3
@KyleStrand Ja, wenn Sie sagen, dass Klassenvorlagenargumente nicht von ihren Konstruktoren abgeleitet werden können, weil [Beispiel, das keinen Konstruktor verwendet] , ist diese Antwort völlig irrelevant. Ich kann wirklich nicht glauben, dass es akzeptiert wurde, +29 erreichte, 6 Jahre brauchte, bis jemand das krasse Problem bemerkte, und 7 Jahre lang ohne eine einzige Ablehnung saß. Denkt sonst niemand beim Lesen oder ...?
underscore_d

1
@underscore_d Mir gefällt, wie diese Antwort in der jetzigen Fassung lautet: "Es könnte einige Probleme mit diesem Vorschlag geben. Ich bin mir nicht sicher, ob das, was ich gerade gesagt habe, Sinn macht (!). Sie können dies gerne kommentieren (!!) Übrigens, so funktioniert C ++ 17 ziemlich genau. "
Kyle Strand

1
@KyleStrand Ah ja, das ist noch ein weiteres Problem, das ich bemerkt habe, aber vergessen habe, unter all den anderen Spaß zu erwähnen. Die Bearbeitung von C ++ 17 wurde nicht vom OP durchgeführt ... und IMO hätte nicht genehmigt werden sollen, sondern als neue Antwort veröffentlicht: Sie wäre als "Ändert die Bedeutung des Beitrags" abgelehnt worden, selbst wenn der Beitrag dies getan hätte Es war nicht bedeutungslos zu beginnen ... Ich war mir nicht bewusst, dass das Bearbeiten in völlig neuen Abschnitten ein faires Spiel war und sicherlich weniger drastische Änderungen abgelehnt wurden, aber ich denke, das ist das Glück der Auslosung in Bezug auf die Rezensenten, die Sie erhalten.
underscore_d

27

Sie können nicht tun, was Sie aus Gründen fragen, die andere angesprochen haben, aber Sie können dies tun:

template<typename T>
class Variable {
    public: Variable(T d) {}
};
template<typename T>
Variable<T> make_variable(T instance) {
  return Variable<T>(instance);
}

was für alle Absichten und Zwecke das gleiche ist, wonach Sie fragen. Wenn Sie die Kapselung lieben, können Sie make_variable zu einer statischen Elementfunktion machen. Das nennen die Leute Konstruktor. Es macht also nicht nur das, was Sie wollen, sondern es wird fast so genannt, wie Sie es wollen: Der Compiler leitet den Template-Parameter vom (benannten) Konstruktor ab.

NB: Jeder vernünftige Compiler optimiert das temporäre Objekt, wenn Sie so etwas schreiben

auto v = make_variable(instance);

6
Ich möchte darauf hinweisen, dass es in einem solchen Fall nicht besonders nützlich ist, eine Funktion als statisches Element zu definieren, da Sie dafür ein Vorlagenargument angeben müssten, damit eine Klasse es trotzdem aufruft, sodass es keinen Sinn macht, es abzuleiten.
Predelnik

3
Und noch besser in C ++ 11 können auto v = make_variable(instance)Sie dies tun, so dass Sie den Typ nicht wirklich angeben müssen
Claudiu

1
Ja, lol bei der Idee, die make-Funktion als staticMitglied zu deklarieren ... denken Sie eine Sekunde darüber nach. Abgesehen davon: Freie Make-Funktionen waren in der Tat die Lösung, aber es ist eine Menge redundanter Boilerplate, die Sie während der Eingabe nur wissen sollten, weil der Compiler Zugriff auf alle Informationen hat, die Sie wiederholen. .. und zum Glück kanonisiert C ++ 17 das.
underscore_d

21

Im aufgeklärten Zeitalter des Jahres 2016, mit zwei neuen Standards, seit diese Frage gestellt wurde, und einem neuen gleich um die Ecke, ist es entscheidend zu wissen, dass Compiler, die den C ++ 17-Standard unterstützen , Ihren Code so kompilieren, wie er ist .

Vorlagenargumentabzug für Klassenvorlagen in C ++ 17

Hier (mit freundlicher Genehmigung von Olzhas Zhumabek über die akzeptierte Antwort) befindet sich das Papier, in dem die relevanten Änderungen des Standards aufgeführt sind.

Bedenken aus anderen Antworten ansprechen

Die aktuell am besten bewertete Antwort

Diese Antwort weist darauf hin, dass "Kopierkonstruktor und operator=" die richtigen Vorlagenspezialisierungen nicht kennen würden.

Dies ist Unsinn, da der Standard-Kopierkonstruktor operator= nur für einen bekannten Vorlagentyp existiert:

template <typename T>
class MyClass {
    MyClass(const MyClass&) =default;
    ... etc...
};

// usage example modified from the answer
MyClass m(string("blah blah blah"));
MyClass *pm;   // WHAT IS THIS?
*pm = m;

Wie ich in den Kommentaren bemerkt habe, gibt es hier keinen Grund für MyClass *pmeine rechtliche Erklärung mit oder ohne die neue Form der Folgerung: MyClass ist kein Typ (es ist eine Vorlage), daher ist es nicht sinnvoll, einen Zeiger von zu deklarieren Typ MyClass. Hier ist eine Möglichkeit, das Beispiel zu beheben:

MyClass m(string("blah blah blah"));
decltype(m) *pm;               // uses type inference!
*pm = m;

Hier pmist bereits vom richtigen Typ, und so ist die Folgerung trivial. Darüber hinaus ist es unmöglich, beim Aufruf des Kopierkonstruktors versehentlich Typen zu mischen :

MyClass m(string("blah blah blah"));
auto pm = &(MyClass(m));

Hier pmwird ein Zeiger auf eine Kopie von sein m. Hier MyClasswird eine Kopie erstellt m, die vom Typ ist MyClass<string>(und nicht vom nicht vorhandenen Typ MyClass). An dem Punkt, an dem auf den pmTyp geschlossen wird, gibt es also genügend Informationen, um zu wissen, dass der Vorlagentyp von mund damit der Vorlagentyp von pmist string.

Darüber hinaus führt Folgendes immer zu einem Kompilierungsfehler :

MyClass s(string("blah blah blah"));
MyClass i(3);
i = s;

Dies liegt daran, dass die Deklaration des Kopierkonstruktors nicht als Vorlage dient:

MyClass(const MyClass&);

Hier stimmt der Vorlagentyp des Copy-Konstruktor-Arguments mit dem Vorlagentyp der Klasse insgesamt überein . dh wenn MyClass<string>instanziiert wird, MyClass<string>::MyClass(const MyClass<string>&);wird damit instanziiert, und wenn MyClass<int>instanziiert wird, MyClass<int>::MyClass(const MyClass<int>&);wird instanziiert. Sofern dies nicht explizit angegeben oder ein Konstruktor mit Vorlagen deklariert ist, gibt es für den Compiler keinen Grund zur Instanziierung MyClass<int>::MyClass(const MyClass<string>&);, was offensichtlich unangemessen wäre.

Die Antwort von Cătălin Pitiș

Pitiș gibt ein Beispiel, das ableitet Variable<int>und Variable<double>dann sagt:

Ich habe den gleichen Typnamen (Variable) im Code für zwei verschiedene Typen (Variable und Variable). Aus meiner subjektiven Sicht beeinträchtigt dies die Lesbarkeit des Codes ziemlich stark.

Wie im vorherigen Beispiel erwähnt, handelt es sich bei sich Variableselbst nicht um einen Typnamen, obwohl die neue Funktion ihn syntaktisch wie einen Namen aussehen lässt.

Pitiș fragt dann, was passieren würde, wenn kein Konstruktor angegeben wird, der die entsprechende Schlussfolgerung zulässt. Die Antwort ist, dass keine Inferenz zulässig ist, da die Inferenz durch den Konstruktoraufruf ausgelöst wird . Ohne einen Konstruktoraufruf gibt es keine Schlussfolgerung .

Dies ähnelt der Frage, welche Version von foohier abgeleitet wird:

template <typename T> foo();
foo();

Die Antwort ist, dass dieser Code aus dem angegebenen Grund illegal ist.

MSalters Antwort

Dies ist, soweit ich das beurteilen kann, die einzige Antwort, die berechtigte Bedenken hinsichtlich der vorgeschlagenen Funktion aufwirft.

Das Beispiel ist:

Variable var(num);  // If equivalent to Variable<int> var(num),
Variable var2(var); // Variable<int> or Variable<Variable<int>> ?

Die Schlüsselfrage ist, wählt der Compiler hier den vom Typ abgeleiteten Konstruktor oder den Kopierkonstruktor aus?

Wenn wir den Code ausprobieren, können wir sehen, dass der Kopierkonstruktor ausgewählt ist. So erweitern Sie das Beispiel :

Variable var(num);          // infering ctor
Variable var2(var);         // copy ctor
Variable var3(move(var));   // move ctor
// Variable var4(Variable(num));     // compiler error

Ich bin mir nicht sicher, wie der Vorschlag und die neue Version des Standards dies spezifizieren. es scheint durch "Abzugsleitfäden" bestimmt zu sein, die ein neues Stück Standard sind, das ich noch nicht verstehe.

Ich bin mir auch nicht sicher, warum der var4Abzug illegal ist; Der Compilerfehler von g ++ scheint darauf hinzudeuten, dass die Anweisung als Funktionsdeklaration analysiert wird.


Was für eine großartige, detaillierte Antwort! var4ist nur ein Fall der "ärgerlichsten Analyse" (nicht im Zusammenhang mit dem Abzug von Vorlagenargumenten). Früher haben wir dafür nur zusätzliche Parens verwendet, aber heutzutage denke ich, dass die Verwendung von Zahnspangen zur eindeutigen Kennzeichnung der Konstruktion der übliche Rat ist.
Sumudu Fernando

@ SumuduFernando Danke! Meinen Sie, dass dies Variable var4(Variable(num));als Funktionsdeklaration behandelt wird? Wenn ja, warum ist Variable(num)eine gültige Parameterspezifikation?
Kyle Strand

@ SumuduFernando Egal, ich hatte keine Ahnung, dass dies gültig ist: coliru.stacked-crooked.com/a/98c36b8082660941
Kyle Strand

11

Es fehlt noch: Der folgende Code ist nicht eindeutig:

int main()
{
    int num = 2;
    Variable var(num);  // If equivalent to Variable<int> var(num),
    Variable var2(var); //Variable<int> or Variable<Variable<int>> ?
}

Ein weiterer guter Punkt. Unter der Annahme, dass eine vom Kopierkonstruktor definierte Variable (Variable <obj> d) vorhanden ist, müsste eine Art Vorrang festgelegt werden.
GRB

1
Oder lassen Sie den Compiler alternativ erneut einen undefinierten Vorlagenparameterfehler auslösen, ähnlich wie ich es in Bezug auf Pitis 'Antwort vorgeschlagen habe. Wenn Sie jedoch diesen Weg einschlagen, wird die Häufigkeit, mit der Inferenzen ohne Probleme (Fehler) auftreten können, immer kleiner.
GRB

Dies ist tatsächlich ein interessanter Punkt, und (wie ich in meiner Antwort bemerkt habe) ich bin mir noch nicht sicher, wie der akzeptierte C ++ 17-Vorschlag dies löst.
Kyle Strand

9

Angenommen, der Compiler unterstützt Ihre Fragen. Dann ist dieser Code gültig:

Variable v1( 10); // Variable<int>

// Some code here

Variable v2( 20.4); // Variable<double>

Jetzt habe ich den gleichen Typnamen (Variable) im Code für zwei verschiedene Typen (Variable und Variable). Aus meiner subjektiven Sicht beeinträchtigt dies die Lesbarkeit des Codes ziemlich stark. Den gleichen Typnamen für zwei verschiedene Typen im gleichen Namespace zu haben, erscheint mir irreführend.

Späteres Update: Noch etwas zu beachten: teilweise (oder vollständige) Vorlagenspezialisierung.

Was ist, wenn ich mich auf Variable spezialisiere und keinen Konstruktor bereitstelle, wie Sie es erwarten?

Also hätte ich:

template<>
class Variable<int>
{
// Provide default constructor only.
};

Dann habe ich den Code:

Variable v( 10);

Was soll der Compiler tun? Verwenden Sie die generische Variablenklassendefinition, um zu schließen, dass es sich um eine Variable handelt, und stellen Sie dann fest, dass Variable keinen Parameterkonstruktor bereitstellt.


1
Schlimmer noch: Was ist, wenn Sie nur Variable <int> :: Variable (float) haben? Sie haben jetzt zwei Möglichkeiten, die Variable (1f) abzuleiten, und keine Möglichkeit, die Variable (1) abzuleiten.
MSalters

Es ist ein guter Punkt, könnte aber durch Casting leicht übertroffen werden: Variable v1 ((doppelt) 10)
jpinto3912

Ich bin damit einverstanden, dass die Lesbarkeit des Codes ein subjektives Problem darstellt. Ich stimme jedoch zu 100% dem zu, was Sie zur Vorlagenspezialisierung sagen. Die Lösung wäre wahrscheinlich, einen undefinierten Vorlagenparameterfehler anzugeben (sobald der Compiler die <int> -Spezialisierung betrachtet und keine gültigen Konstruktoren sieht, muss er sagen, dass er keine Ahnung hat, welche Vorlage Sie verwenden möchten und dass Sie dies explizit angeben müssen) Ich stimme zu, dass es keine schöne Lösung ist. Ich würde dies als eine weitere wichtige syntaktische Lücke hinzufügen, die behandelt werden müsste (aber gelöst werden könnte, wenn man die Konsequenzen akzeptiert).
GRB

4
@ jpinto3912 - Sie verpassen den Punkt. Der Compiler muss ALLE möglichen Variablen <T> instanziieren, um zu überprüfen, ob JEDE ctor-Variable <T> :: Variable einen mehrdeutigen ctor liefert. Die Mehrdeutigkeit loszuwerden ist nicht das Problem - instanziieren Sie einfach die Variable <double> selbst, wenn Sie dies möchten. Es geht in erster Linie darum, diese Mehrdeutigkeit zu finden, die es unmöglich macht.
MSalters

6

Der C ++ 03- und der C ++ 11-Standard erlauben keine Ableitung von Vorlagenargumenten von den an den Konstruktor übergebenen Parametern.

Es gibt jedoch einen Vorschlag für die "Ableitung von Vorlagenparametern für Konstruktoren", damit Sie möglicherweise bald das bekommen, wonach Sie fragen. Bearbeiten: Diese Funktion wurde für C ++ 17 bestätigt.

Siehe: 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


Die Funktion wurde zu C ++ 17 hinzugefügt, jedoch nicht, wenn "bald" für einen Zeitraum von 6 bis 8 Jahren gilt. ;)
ChetS

2

Viele Klassen hängen nicht von Konstruktorparametern ab. Es gibt nur wenige Klassen, die nur einen Konstruktor haben und basierend auf den Typen dieses Konstruktors parametrisieren.

Wenn Sie wirklich eine Vorlageninferenz benötigen, verwenden Sie eine Hilfsfunktion:

template<typename obj>
class Variable 
{
      obj data;
public: 
      Variable(obj d)
      : data(d)
      { }
};

template<typename obj>
inline Variable<obj> makeVariable(const obj& d)
{
    return Variable<obj>(d);
}

1
Natürlich würde sich diese Funktionalität nur für einige Klassen als nützlich erweisen, aber das Gleiche gilt für die Funktionsinferenz. Nicht alle Vorlagenfunktionen beziehen ihre Parameter auch aus der Argumentliste, wir lassen jedoch Rückschlüsse auf die Funktionen zu, die dies tun.
GRB

1

Die Ableitung von Typen ist auf Vorlagenfunktionen in aktuellem C ++ beschränkt, aber es ist seit langem bekannt, dass die Ableitung von Typen in anderen Kontexten sehr nützlich wäre. Daher C ++ 0x auto.

Während genau das , was Sie vorschlagen, in C ++ 0x nicht möglich ist, zeigt das Folgende, dass Sie ziemlich nahe kommen können:

template <class X>
Variable<typename std::remove_reference<X>::type> MakeVariable(X&& x)
{
    // remove reference required for the case that x is an lvalue
    return Variable<typename std::remove_reference<X>::type>(std::forward(x));
}

void test()
{
    auto v = MakeVariable(2); // v is of type Variable<int>
}

0

Sie haben Recht, der Compiler könnte es leicht erraten, aber soweit ich weiß, ist es nicht im Standard oder C ++ 0x, sodass Sie mindestens weitere 10 Jahre warten müssen (ISO-Standards mit fester Umkehrrate), bevor Compiller-Anbieter diese Funktion hinzufügen


Das ist mit dem kommenden Standard nicht korrekt. Ein Auto-Keyword wird eingeführt. Schauen Sie sich den Beitrag von James Hopkins in diesem Thread an. stackoverflow.com/questions/984394/… . Er zeigt, wie es in C ++ 0x möglich sein wird.
Ovanes

1
Um mich selbst zu korrigieren, ist das Auto-Schlüsselwort auch im aktuellen Standard vorhanden, jedoch für den anderen Zweck.
Ovanes

Sieht so aus, als wären es 8 Jahre (ab dem Zeitpunkt dieser Antwort) ... also waren 10 Jahre keine schlechte Vermutung, obwohl es in der Zwischenzeit zwei Standards gegeben hat!
Kyle Strand

-1

Schauen wir uns das Problem mit Bezug auf eine Klasse an, mit der jeder vertraut sein sollte - std :: vector.

Erstens besteht eine sehr häufige Verwendung von Vektoren darin, den Konstruktor zu verwenden, der keine Parameter akzeptiert:

vector <int> v;

In diesem Fall kann offensichtlich keine Inferenz durchgeführt werden.

Eine zweite häufige Verwendung ist das Erstellen eines Vektors mit Vorgröße:

vector <string> v(100);

Hier, wenn Inferenz verwendet wurde:

vector v(100);

Wir erhalten einen Vektor von Ints, keine Strings, und vermutlich ist er nicht dimensioniert!

Betrachten Sie zum Schluss Konstruktoren, die mehrere Parameter annehmen - mit "Inferenz":

vector v( 100, foobar() );      // foobar is some class

Welcher Parameter sollte für die Inferenz verwendet werden? Wir müssten dem Compiler sagen, dass es der zweite sein sollte.

Bei all diesen Problemen für eine Klasse, die so einfach wie ein Vektor ist, ist leicht zu erkennen, warum keine Inferenz verwendet wird.


3
Ich denke, Sie verstehen die Idee falsch. Typinferenz für Konstruktoren würde nur auftreten, wenn der Vorlagentyp Teil des Konstruktors ist. Angenommen, der Vektor hat die Vorlagendefinitionsvorlage <Typname T>. Ihr Beispiel ist kein Problem, da der Konstruktor des Vektors als Vektor (int-Größe) und nicht als Vektor (T-Größe) definiert wird. Nur im Fall eines Vektors (T-Größe) würde eine Folgerung auftreten; Im ersten Beispiel würde der Compiler einen Fehler ausgeben, der besagt, dass T undefiniert ist. Im Wesentlichen identisch mit der Funktionsweise der Funktionsvorlageninferenz.
GRB

Es würde also nur für Konstruktoren stattfinden, die einen einzelnen Parameter haben und bei denen dieser Parameter ein Vorlagenparametertyp ist? Das scheint eine verschwindend kleine Anzahl von Fällen zu sein.

Es muss nicht unbedingt ein einzelner Parameter sein. Zum Beispiel könnte man einen Vektorkonstruktor des Vektors haben (int size, T firstElement). Wenn eine Vorlage mehrere Parameter hat (Vorlage <Typname T, Typname U>), könnte man Holder :: Holder (T firstObject, U secondObject) haben. Wenn eine Vorlage mehrere Parameter hat, der Konstruktor jedoch nur einen davon verwendet, z. B. Holder (U secondObject), muss T immer explizit angegeben werden. Die Regeln sollen der Inferenz von Funktionsvorlagen so ähnlich wie möglich sein.
GRB

-2

Wenn Sie den Ctor zu einer Vorlage machen, kann die Variable nur eine Form, aber verschiedene Ctors haben:

class Variable {
      obj data; // let the compiler guess
      public:
      template<typename obj>
      Variable(obj d)
       {
           data = d;
       }
};

int main()
{
    int num = 2;
    Variable var(num);  // Variable::data int?

    float num2 = 2.0f;
    Variable var2(num2);  // Variable::data float?
    return 0;         
}

Sehen? Wir können nicht mehrere Variable :: data-Mitglieder haben.


Das würde unter keinen Umständen Sinn machen. obj in Bezug auf obj-Daten ist undefiniert, da diese Klasse keine Vorlage mehr ist. Ein solcher Code wäre in beiden Fällen ungültig.
GRB

Ich wollte das von Ihnen beschriebene Compiler-Verhalten, also finde ich einen Weg, um diese Einschränkung (in meinem Fall) zu umgehen, die Sie vielleicht interessant finden: stackoverflow.com/questions/228620/garbage-collection-in-c-why/…
Nick Dandoulakis

-2

Siehe Den C ++ Template - Argument Abzug für weitere Informationen zu diesem Thema .


4
Ich habe diesen Artikel schon einmal gelesen und es schien nicht viel über das zu sprechen, was ich sage. Der Autor scheint nur dann über Argumentableitung in Bezug auf Klassen zu sprechen, wenn er sagt, dass dies nicht oben im Artikel möglich ist;) - wenn Sie auf die Abschnitte hinweisen könnten, die Sie für relevant halten, obwohl ich ' Ich würde das wirklich schätzen.
GRB
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.