为什么编译器在某些情况下只能将 char * 隐式转换为 std::string
Why can compiler only implicitly convert char * to std::string in some cases
这些工作:
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
。所以也许这就是原因,但我不确定。
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";}
需要两次 user-defined 隐式转换;一个到 std::string
,另一个到 WithString
。那是不可能的。
这里只有一个隐式转换(到 std::string
):
takeString("hello");
这里也是一样,因为后面的"conversion"到WithString
是显式的:
WithString("hello");
I can get the behavior to work by doing this:
struct WithString {
WithString(std::string){};
WithString(const char *){};
};
是的,这就是你应该做的。
你的方法:
WithString makeWithString() { return "hello";}
需要两次转换:隐式的 const char *
到 std::string
转换,然后是 WithString
对象的构造。 C++ 最多允许其中之一隐式发生。另请参阅此处的讨论:
Non-const copy constructor and implicit conversions on return value
阅读 C++ 标准中的 implicit conversions 部分。我在 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;
另见 copy initialization。在注释中它明确调用 WithString t = "hello";
一个错误。
这些工作:
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
。所以也许这就是原因,但我不确定。
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";}
需要两次 user-defined 隐式转换;一个到 std::string
,另一个到 WithString
。那是不可能的。
这里只有一个隐式转换(到 std::string
):
takeString("hello");
这里也是一样,因为后面的"conversion"到WithString
是显式的:
WithString("hello");
I can get the behavior to work by doing this:
struct WithString { WithString(std::string){}; WithString(const char *){}; };
是的,这就是你应该做的。
你的方法:
WithString makeWithString() { return "hello";}
需要两次转换:隐式的 const char *
到 std::string
转换,然后是 WithString
对象的构造。 C++ 最多允许其中之一隐式发生。另请参阅此处的讨论:
Non-const copy constructor and implicit conversions on return value
阅读 C++ 标准中的 implicit conversions 部分。我在 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;
另见 copy initialization。在注释中它明确调用 WithString t = "hello";
一个错误。