简体   繁体   English

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?
}

I'm using VS 2013. 我正在使用VS 2013。

Questions: 问题:

  1. Why do the definitions of str1 and str2 lead to different compile errors? 为什么str1str2的定义会导致不同的编译错误?

  2. As I know, when rStr is created, a temporary string object is created firstly, then rStr will refer to the temporary. 据我所知,当创建rStr时, rStr创建一个临时字符串对象,然后rStr将引用临时对象。 But, why does the creation of the temporary object not lead a compile error? 但是,为什么创建临时对象不会导致编译错误? Is there any different between tmp and strN ? tmpstrN之间有什么不同吗?

The first definition, std::string str1(myStr); 第一个定义, std::string str1(myStr); is indeed ambigous: 确实很暧昧:

std::string str1(myStr.operator char*());
// or
std::string str1(myStr.operator std::string());

so this initialization fails due to an ambiguity. 所以这种初始化由于模糊而失败。

This is essentially the same scenario as 这与基本相同

void foo(char const*);
void foo(std::string);

foo(myStr); // ambiguous

Exactly one user-defined conversion is required, then a function will be called (for the first definition, the function is a constructor). 只需要一个用户定义的转换,然后调用一个函数(对于第一个定义,函数是构造函数)。 Both conversions are viable, and neither is a subset of the other, so both have the same rank. 两种转换都是可行的,并且两者都不是另一种的子集,因此两者都具有相同的排名。


The second definition, std::string str2 = myStr; 第二个定义, std::string str2 = myStr; is actually fine . 其实很好 Only one user-defined conversion to std::string is allowed, either via a constructor or via a conversion function, not both. 仅一个用户定义的转换 std::string是允许的,或者通过一个构造或通过转换功能,而不是两个。 So only std::string str2 = myStr.operator std::string(); 所以只有std::string str2 = myStr.operator std::string(); is viable. 是可行的。

Note string str2 = expr; 注意string str2 = expr; when expr is not of type string requires the expr to be converted to std::string . expr不是string类型时,需要将expr 转换为std::string The resulting temporary is then used to initialize str2 via a copy/move: 然后使用生成的临时值通过复制/移动初始化str2

string str2 = string(expr);
//            ~~~~~~ implicit

Therefore, the conversion on the right hand side must convert directly to std::string , otherwise you would need a chain of two user-defined conversions to initialize the temporary: (UDC = User-Defined Conversion) 因此,右侧的转换必须直接转换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

For example, expr to char const* via the operator char* and then to a std::string via the converting constructor requires a chain of two user-defined conversions => not viable. 例如, exprchar const*通过operator char*然后通过转换构造函数到std::string需要一个由两个用户定义的转换链=>不可行。 If we try to use the operator char*() conversion, we need an additional constructor implicit constructor call to make the RHS a string . 如果我们尝试使用operator char*()转换,我们需要一个额外的构造函数隐式构造函数调用来使RHS成为一个string

This is different from string str1( expr ) , where expr does not need to be converted implicitly to string . 这与string str1( expr ) ,其中expr不需要隐式转换为string It might have to be converted to initialize a parameter of a string constructor. 可能必须转换为初始化字符串构造函数的参数。 The direct initialization of str1 from the possibly converted expr is not a(n implicit) conversion itself, but just a function call. 可能转换的 expr直接初始化str1不是(n隐式)转换本身,而只是函数调用。 No extra temporary is created: 没有创建额外的临时:

string str1( expr );
// resolved as:
string str1( expr.operator string() ); // fine
string str1( expr.operator char* () ); // fine

This second definition is refused when compiling with enabled language extension. 使用启用的语言扩展进行编译时第二个定义被拒绝。 Without language extensions, this initialization is fine in VS2013 Update 2. 没有语言扩展,这种初始化在VS2013 Update 2中很好。


The third one follows a different initialization scheme. 第三个遵循不同的初始化方案。 It should behave like the second one in this case, as far as I can tell. 据我所知,在这种情况下它应该像第二个一样。 The language extensions seems to apply only to the second one but not to the third one, it seems. 似乎语言扩展似乎仅适用于第二个,但不适用于第三个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM