3

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

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. Поэтому, возможно, это и есть причина, но я не уверен.

ответ

2

Ваш метод:

WithString makeWithString() { return "hello";} 

необходимы два преобразования: неявный Const преобразовывался - * - к станду :: преобразование строки, затем строительство WithString объекта. C++ позволяет не более одного из них неявно. Смотрите также обсуждение здесь:

Non-const copy constructor and implicit conversions on return value

5

I would say it is because in the first two working cases, the conversion is between const char * to std::string, but in the error case, this would instead require a chain of 2 conversion, first from const char * to std::string, and then from std::string to WithString. So perhaps that is the reason, but I'm not sure.

Точно.

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

WithString makeWithString() { return "hello";} 

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

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

takeString("hello"); 

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

WithString("hello"); 

I can get the behavior to work by doing this:

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

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

-2

Читайте implicit conversions раздел в стандарте 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 неверен (рассматривающей преобразование из сопзЬ символ * в строке как стандартного преобразования).Следующий код должен работать в соответствии со стандартом, но выдает ошибку в VS2015:

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

Смотрите также copy initialization. В заметках он явно вызывает ошибку WithString t = "hello";.

+0

Если MSVS 2015 допускает это, он не работает. Мне интересно, какие функции C++ 11, C++ 14, C++ 17 вы должны разрешить этой программе? –

+0

Действительно, MSVS 2015 C++ позволяет это. Я думаю, вопрос заключается в том, является ли const char * для std: string - это стандартное преобразование_ или нет. Если это так, то это правильно; если нет (т. е. пользовательское преобразование), то это не так. Наведение «привет» в Visual Studio для всех случаев дает std :: string :: basic_string (const char * _Ptr). – vdovydaitis3

+0

И, да, я нахожу дополнительную заметку в разделе [инициализация копирования] (http://en.cppreference.com/w/cpp/language/copy_initialization): неявное преобразование в инициализации копии должно производить Т непосредственно из инициализатора, например. прямая инициализация ожидает неявного преобразования из инициализатора в аргумент конструктора Т. struct S {S (std :: string) {}}; // неявно конвертируется из std :: string S s ("abc"); // OK: преобразование из const char [4] в std :: string S s = "abc"; // Ошибка: нет преобразования из const char [4] в S S s = "abc" s; // OK: преобразование из std :: string в S – vdovydaitis3

 Смежные вопросы

  • Нет связанных вопросов^_^