Comment appeler le bon constructeur d'un type de modèle?


21

Dans le code suivant, comment puis-je faire fonctionner la ligne commentée de la même manière que la ligne juste au-dessus?

Je voudrais en faire un code générique, qui appelle le constructeur approprié d'un modèle 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;
}

Réponses:


14

Utilisez l'initialisation directe:

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

17

Utilisez braced-init-list (ou uniform-initiation) pour initialiser l'instance de Class.

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

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

est la copie-initialisation . Cela ne fonctionne pas, car cela impliquerait deux conversions définies par l'utilisateur:

  • de const char*à std::string,
  • du std::stringau Class<std::string>.

Mais tout au plus est autorisé.

Quand tu écris

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

vous utilisez l'initialisation directe . Cela fonctionne car maintenant une seule conversion définie par l'utilisateur est utilisée:

  • du const char*au std::string.

0

Si vous pouvez modifier votre Class, vous pouvez ajouter un constructeur de conversion basé sur des modèles. Vous pourrez alors compiler la ligne commentée comme écrit dans votre exemple. Notez cependant qu'il n'est généralement pas recommandé d'utiliser des conversions implicites sans raison décente car elles peuvent entraîner des bogues difficiles à repérer (cf. les lignes directrices de 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;
}

Si vous pouvez utiliser C ++ 14, vous pouvez utiliser le std::literals::string_literals::operator""set supprimer le constructeur de conversion. Ensuite, votre ligne ressemblerait à ceci:

using namespace std::literals;

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

Code en direct ici .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.