C2664 при прямой передаче параметра функции

class Person
{
public:
    template <
        typename T,
        typename = std::enable_if_t<
            !std::is_base_of<Person,std::decay_t<T>>::value &&
            !std::is_integral<std::remove_reference_t<T>>::value
        >
    >
        explicit Person(T&& n) :
        name(std::forward<T>(n))
    {

    }
private:
    std::string name;
};

int main()
{
    Person p(u"Konrad Zuse");
    std::cout << "Hello World!\n";
}

При компиляции вижу ошибку C2664

"std::basic_string<char,std::char_traits,std::allocator>::basic_string(std::initializer_list<_Elem>,const _Alloc &)": невозможно преобразовать аргумент 1 из "const char16_t [12]" в "std::initializer_list<_Elem>" ConsoleApplication2 C:\Users\Александр\source\repos\ConsoleApplication2\ConsoleApplication2\ConsoleApplication2.cpp 31

Объясните это поведение во всех подробностях, пожалуйста.


Ответы (1 шт):

Автор решения: KoVadim

Давайте подумаем, а какой тип у u"Konrad Zuse" ? char const[12] - нет. Если бы он был такой, то тогда у строки std::string нашелся бы подходящий конструктор. Проверяем - удаляем просто буковку u и все компилируется (ожидаемо, потому что теперь тип действительно char const[12]).

У строки u"Konrad Zuse" тип wchar_t const[12] (хотя некоторые компиляторы говорят char16_t const[12], но это для них одно и тоже обычно) - массив широких символов. Поэтому, нужно исправить объявление на std::u16string name; (у типа u16string есть нужный конструктор) или делать преобразование типов.

То есть, код не компилируется, потому что компилятор не может найти подходящее разрешенное преобразование.

→ Ссылка