Эти работы:
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
, Так что, возможно, в этом причина, но я не уверен.
Ваш метод:
WithString makeWithString() { return "hello";}
требуется два преобразования: неявное преобразование const-char — * — to-std :: string, затем конструкция WithString
объект. C ++ позволяет не более чем одному из них происходить неявно. Смотрите также обсуждение здесь:
Неконстантный конструктор копирования и неявные преобразования возвращаемого значения
Я бы сказал, что это потому, что в первых двух рабочих случаях преобразование происходит между 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 *){}; };
Да, это то, что вы должны сделать.
Читать неявные преобразования раздел в стандарте 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";
ошибка.