C++11 隐式转换
C++11 implicitly convert
#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?
}
我正在使用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());
因此,由于歧义,此初始化失败。
这本质上与
void foo(char const*);
void foo(std::string);
foo(myStr); // ambiguous
只需要一个用户定义的转换,然后将调用一个函数(对于第一个定义,该函数是构造函数(。两种转换都是可行的,并且两者都不是另一个的子集,因此两者具有相同的排名。
第二个定义,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
因此,右侧的转换必须直接转换为 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
例如,expr
通过operator char*
char const*
,然后通过转换构造函数std::string
需要两个用户定义的转换链 => 不可行。如果我们尝试使用operator char*()
转换,我们需要一个额外的构造函数隐式构造函数调用来使 RHS 成为string
。
这与string str1( expr )
不同,expr
不需要隐式转换为string
。可能必须转换它才能初始化字符串构造函数的参数。从可能转换的expr
直接初始化str1
本身不是隐式转换本身,而只是一个函数调用。不会创建额外的临时:
string str1( expr );
// resolved as:
string str1( expr.operator string() ); // fine
string str1( expr.operator char* () ); // fine
在使用启用的语言扩展进行编译时,将拒绝第二个定义。如果没有语言扩展,此初始化在VS2013更新2中是正常的。
第三个遵循不同的初始化方案。据我所知,在这种情况下,它的行为应该类似于第二个。语言扩展似乎仅适用于第二个,而不适用于第三个。
- 如何将模板转换为C++11之前的模板
- 如何在 C++11 中将标准::字符串转换为标准::u32字符串?
- 如何将Javascript正则表达式转换为C++11正则表达式
- 从c++11 time_t创建一个可转换为.net DateTime的字符串
- C++11 模板函数"implicity"将位集<N>转换为"unsigned long"
- 从迭代器转换为变量的类型.(C++11 模板)
- C++11中的自动类型扣除和类型转换有什么区别
- 如何将元组转换为C 11中的字节数组
- C 11:为什么RVALUE参考参数隐式转换为LVALUE
- ISO C++11 不允许从字符串转换为字符
- 在 C++11 中将静态 constexpr 数组转换为模板参数
- 尝试将 C++11 代码转换为 C++03 时默认函数模板参数出错
- 将字符串元素转换为整数 (C++11)
- 对C 98和C 11的停止隐式转换
- C++11 何时相对于运算符优先级进行算术类型转换
- C++11自动.从float转换为long
- C 11中函数参数的显式模板函数参数规范和隐式转换
- C++11 unique_ptr和shared_ptr能够转换为彼此的类型吗?
- 如何在不提升的情况下将 C++11 代码转换为 C++98
- 转换基数 11 到十进制