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


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

Ответы:



17

Используйте braced-init-list (илиiform-initiation) для инициализации экземпляра 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 ++ ).

#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.