Come chiamare il costruttore giusto di un tipo di modello?


21

Nel codice seguente, come posso fare in modo che la riga commentata funzioni allo stesso modo della riga appena sopra?

Vorrei renderlo un codice generico, che chiama il costruttore adatto di un modello 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;
}

Risposte:


14

Usa inizializzazione diretta:

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

17

Utilizzare braced-init-list (o uniform-initiation) per inizializzare l'istanza di Class.

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

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

è l' inizializzazione della copia . Non funziona perché comporterebbe due conversioni definite dall'utente:

  • da const char*a std::string,
  • da std::stringa Class<std::string>.

Ma al massimo uno è permesso.

Quando scrivi

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

si utilizza l'inizializzazione diretta . Funziona perché ora viene utilizzata solo una conversione definita dall'utente:

  • da const char*a std::string.

0

Se sei in grado di cambiare il tuo Class, potresti aggiungere un costruttore di conversione basato su modelli. Quindi sarai in grado di compilare la riga commentata come scritto nel tuo esempio. Si noti, tuttavia, che in genere non è consigliabile utilizzare conversioni implicite senza una ragione decente in quanto potrebbero causare bug difficili da individuare (vedere le Linee guida di base C ++ ).

#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;
}

Se è possibile utilizzare C ++ 14, è possibile utilizzare std::literals::string_literals::operator""se rimuovere il costruttore di conversione. Quindi, la tua linea sarebbe simile a questa:

using namespace std::literals;

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

Codice live qui .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.