Leo*_*all 8 c++ implicit-conversion c++11
#include <string>
struct String
{
template<typename T> operator T*() { return 0; }
operator std::string() { return ""; }
};
int main()
{
String myStr;
std::string str1(myStr); // ambiguous, error C2668
std::string str2 = myStr; // error C2440:
// 'initializing' : cannot convert from 'String' to
// `std::basic_string<char,std::char_traits<char>,std::allocator<char>>',
// No constructor could take the source type,
// or constructor overload resolution was ambiguous
const std::string& rStr = myStr; // Ok, but why?
}
Run Code Online (Sandbox Code Playgroud)
我正在使用VS 2013.
问题:
为什么定义str1和str2导致不同的编译错误?
据我所知,在rStr创建时,首先创建一个临时字符串对象,然后rStr引用临时对象.但是,为什么创建临时对象不会导致编译错误?有没有之间的不同tmp和strN?
第一个定义std::string str1(myStr);确实是不明确的:
std::string str1(myStr.operator char*());
// or
std::string str1(myStr.operator std::string());
Run Code Online (Sandbox Code Playgroud)
所以这种初始化由于模糊而失败.
这与基本相同
void foo(char const*);
void foo(std::string);
foo(myStr); // ambiguous
Run Code Online (Sandbox Code Playgroud)
只需要一个用户定义的转换,然后调用一个函数(对于第一个定义,函数是构造函数).两种转换都是可行的,并且两者都不是另一种的子集,因此两者都具有相同的排名.
第二个定义,std::string str2 = myStr;实际上很好.只有一个用户定义的转换到 std::string被允许,或者通过一个构造或通过转换功能,而不是两个.所以只有std::string str2 = myStr.operator std::string();可行.
注意string str2 = expr;当expr不为类型的string需要expr被转换为std::string.然后使用生成的临时值str2通过复制/移动进行初始化:
string str2 = string(expr);
// ~~~~~~ implicit
Run Code Online (Sandbox Code Playgroud)
因此,右侧的转换必须直接转换为std::string,否则您需要两个用户定义的转换链来初始化临时:( UDC =用户定义的转换)
string str2 = string(expr);
// resolved as:
string str2 = expr.operator string(); // fine: one implicit UDC
string str2 = string(expr.operator char*()); // error: two UDCs
Run Code Online (Sandbox Code Playgroud)
例如,expr以char const*通过operator char*,然后到一个std::string经由所述转换构造需要两个用户定义的转换=>不可行的链.如果我们尝试使用operator char*()转换,我们需要一个额外的构造函数隐式构造函数调用来使RHS成为一个string.
这不同于string str1( expr ),expr不需要隐式转换为string.它可能必须转换到初始化字符串的构造函数的参数.str1从可能转换 的直接初始化expr不是(n隐式)转换本身,而只是函数调用.没有创建额外的临时:
string str1( expr );
// resolved as:
string str1( expr.operator string() ); // fine
string str1( expr.operator char* () ); // fine
Run Code Online (Sandbox Code Playgroud)
使用启用的语言扩展进行编译时,第二个定义被拒绝.没有语言扩展,这种初始化在VS2013 Update 2中很好.
第三个遵循不同的初始化方案.据我所知,在这种情况下它应该像第二个一样.似乎语言扩展似乎仅适用于第二个,但不适用于第三个.
| 归档时间: |
|
| 查看次数: |
716 次 |
| 最近记录: |