4

这些工作:

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 *to之间std::string,但在错误情况下,这将需要一个 2 转换链,首先是 from const char *to std::string,然后是 from std::stringto WithString。所以也许这就是原因,但我不确定。

4

3 回答 3

6

我想说这是因为在前两个工作情况下,转换是在 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 *){};
};

是的,这就是你应该做的。

于 2017-01-15T14:49:58.980 回答
3

你的方法:

WithString makeWithString() { return "hello";}

需要两次转换:隐式const char *转换std::string,然后是WithString对象的构造。C++ 最多允许其中一种隐式发生。另请参阅此处的讨论:

非常量复制构造函数和返回值的隐式转换

于 2017-01-15T14:54:41.293 回答
-1

阅读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* 到 string 的转换视为标准转换)。以下代码应该按照标准工作,但在 VS2015 中会产生错误:

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

另请参见复制初始化。在注释中它明确地调用WithString t = "hello";了一个错误。

于 2017-01-15T15:18:15.680 回答