Як викликати правильний конструктор типу шаблону?


21

У наступному коді, як я можу змусити коментований рядок працювати так само, як і рядок прямо над ним?

Я хотів би зробити це загальним кодом, який викликає відповідний конструктор шаблону 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;
}

Відповіді:


14

Використовуйте пряму ініціалізацію:

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

17

Використовуйте braced-init-list (або уніфіковану ініціацію) для ініціалізації екземпляра Class.

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

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

є ініціалізацією копіювання . Це не працює, оскільки передбачає дві конверсії, визначені користувачем:

  • від const char*до std::string,
  • від std::stringдо Class<std::string>.

Але максимум одне дозволено.

Коли пишеш

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

ви використовуєте пряму ініціалізацію . Це працює, тому що зараз використовується лише одна визначена користувачем конверсія:

  • від const char*до std::string.

0

Якщо ви можете змінити свій Class, ви можете додати конструктор шаблону перетворення. Тоді ви зможете скласти коментований рядок, як написано у вашому прикладі. Однак зауважте, що, як правило, не рекомендується використовувати неявні перетворення без поважних причин, оскільки вони можуть призвести до важких помилок (див. C ++ Core Guidlines ).

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

Якщо ви можете використовувати C ++ 14, ви можете використати std::literals::string_literals::operator""sконструктор перетворення та видалити його. Тоді ваш рядок виглядатиме так:

using namespace std::literals;

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

Живий код тут .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.