Wie rufe ich den richtigen Konstruktor eines Vorlagentyps auf?


21

Wie kann ich im folgenden Code dafür sorgen, dass die kommentierte Zeile genauso funktioniert wie die Zeile direkt darüber?

Ich möchte daraus einen generischen Code machen, der einen geeigneten Konstruktor einer Vorlage aufruft Type.

#include <string>
#include <iostream>

template <typename Type>
struct Class
{
    Type data;
    Class(Type data) : data(data) { }
};

int main()
{
    Class<std::string> a = std::string("abc");
    // Class<std::string> b = "abc";
    std::cout << a.data << std::endl;
    return 0;
}

Antworten:


14

Verwenden Sie die direkte Initialisierung:

Class<std::string> b("abc");

17

Verwenden Sie die Klammer-Init-Liste (oder die Uniform-Initiation), um die Instanz von zu initialisieren Class.

Class<std::string> a{ std::string("abc") };  // works
Class<std::string> b{ "abc" };               // also works

13
Class<std::string> b = "abc";

ist Kopierinitialisierung . Es funktioniert nicht, da zwei benutzerdefinierte Konvertierungen erforderlich wären:

  • von const char*bis std::string,
  • von std::stringbis Class<std::string>.

Aber höchstens einer ist erlaubt.

Wenn du schreibst

Class<std::string> b("abc");
// or
Class<std::string> b{"abc"};

Sie verwenden die Direktinitialisierung . Es funktioniert, weil jetzt nur eine benutzerdefinierte Konvertierung verwendet wird:

  • von const char*bis std::string.

0

Wenn Sie Ihre ändern können Class, können Sie einen Konstruktor für die Konvertierung von Vorlagen hinzufügen. Dann können Sie die kommentierte Zeile wie in Ihrem Beispiel beschrieben kompilieren. Beachten Sie jedoch, dass es im Allgemeinen nicht empfohlen wird, implizite Konvertierungen ohne triftigen Grund zu verwenden, da dies zu schwer zu erkennenden Fehlern führen kann (siehe C ++ - Kernrichtlinien ).

#include <string>
#include <iostream>

template <typename Type>
struct Class
{
    Type data;
    Class(Type data) : data(data) { }

    template<typename Other>
    Class(Other other_data) : data(other_data) {}
};


int main()
{
    Class<std::string> a = std::string("abc");
    Class<std::string> b = "abc";
    Class<std::string> c = a;

    std::cout << b.data << std::endl;
    return 0;
}

Wenn Sie C ++ 14 verwenden können, können Sie std::literals::string_literals::operator""sden konvertierenden Konstruktor verwenden und entfernen. Dann würde Ihre Linie so aussehen:

using namespace std::literals;

Class<std::string> b = "abc"s;

Live-Code hier .

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.