这些工作:
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]'...
如果在前两种情况下"hello"被隐式转换为std::string
,为什么在最后一种情况下不能不这样做?请注意,我没有将WithString
构造函数指定为 explicit
,所以我期待这样的转换。
我可以通过这样做来使行为工作:
struct WithString {
WithString(std::string){};
WithString(const char *){};
};
我只是对这种奇怪感到好奇。如果我假设一个猜测,我会说这是因为在前两个工作案例中,转换在 const char *
到 std::string
之间,但在错误情况下,这将需要一个 2 的转换链,首先从 const char *
到 std::string
,然后从 std::string
到 WithString
。所以也许这就是原因,但我不确定。
我会说这是因为在前两个工作情况下,转换是在 const char * 到 std::string 之间,但在错误情况下,这将需要一个 2 的链,首先从 const char * 到 std::string,然后从 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 *){}; };
是的,这是你应该做的。
您的方法:
WithString makeWithString() { return "hello";}
需要两个转换:隐式const char *
-to- std::string
转换,然后是WithString
对象的构造。C++最多允许其中之一隐式发生。另请参阅此处的讨论:
返回值上的非常量复制构造函数和隐式转换
读取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";
错误。