Почему в некоторых случаях компилятор может неявно преобразовывать char * в std :: string

Эти работы:

struct WithString {
WithString(std::string){};
};

void takeString(std::string){}

//implicit conversions:
takeString("hello");
WithString("hello");

Но это не так:

WithString makeWithString() { return "hello";}

// error: no viable conversion from returned value of type 'const char [6]'...

Если «привет» неявно преобразуется в std::string в первых двух случаях почему бы не быть в последнем случае? Обратите внимание, что я не указал WithString конструктор как explicit, так что я ожидаю такого преобразования.

Я могу заставить поведение работать следующим образом:

struct WithString {
WithString(std::string){};
WithString(const char *){};
};

Мне просто любопытно об этой странности. Если я постулирую предположение, я бы сказал, что это потому, что в первых двух рабочих случаях преобразование происходит между const char * в std::string, но в случае ошибки вместо этого потребуется преобразование цепочки из 2, сначала из const char * в std::stringа затем из std::string в WithString, Так что, возможно, в этом причина, но я не уверен.

3

Решение

Ваш метод:

WithString makeWithString() { return "hello";}

требуется два преобразования: неявное преобразование const-char — * — to-std :: string, затем конструкция WithString объект. C ++ позволяет не более чем одному из них происходить неявно. Смотрите также обсуждение здесь:

Неконстантный конструктор копирования и неявные преобразования возвращаемого значения

2

Другие решения

Я бы сказал, что это потому, что в первых двух рабочих случаях преобразование происходит между const char * в std :: string, но в случае ошибки вместо этого потребуется преобразование цепочки из 2, сначала из const char * в std: : строка, а затем из std :: string в WithString. Так что, возможно, в этом причина, но я не уверен.

Именно так.

Без вашего const char* перегрузка конструктора, это:

WithString makeWithString() { return "hello";}

потребует двух пользовательских неявных преобразований; один к std::string и другой, чтобы WithString, Это невозможно.

Здесь, однако, есть только одно неявное преобразование (в std::string):

takeString("hello");

И то же самое здесь, потому что последующее «преобразование» в WithString явно:

WithString("hello");

Я могу заставить поведение работать следующим образом:

struct WithString {
WithString(std::string){};
WithString(const char *){};
};

Да, это то, что вы должны сделать.

5

Читать неявные преобразования раздел в стандарте C ++. Я попробовал следующий код в VS 2015, и он скомпилирован без ошибок.

#include <string>

struct WithString {
WithString(std::string) {};
};

void takeString(std::string) {}

//implicit conversions:
void someFunc()
{
takeString("hello");
WithString("hello");
WithString t = "hello";
}

WithString makeWithString() { return "hello"; }

Похоже, что VS2015 является неправильным (преобразование из const char * в строку как стандартное преобразование). Следующий код должен работать в соответствии со стандартом, но выдает ошибку в VS2015:

WithString makeWithString() { return "hello"s; }
WithString t = "hello"s;

Смотрите также инициализация копии. В примечаниях это явно вызывает WithString t = "hello"; ошибка.

-2
По вопросам рекламы [email protected]