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

我正在使用VS 2013。

問題:

  1. 為什么str1str2的定義會導致不同的編譯錯誤?

  2. 據我所知,當創建rStr時, rStr創建一個臨時字符串對象,然后rStr將引用臨時對象。 但是,為什么創建臨時對象不會導致編譯錯誤? tmpstrN之間有什么不同嗎?

第一個定義, 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

例如, exprchar const*通過operator char*然后通過轉換構造函數到std::string需要一個由兩個用戶定義的轉換鏈=>不可行。 如果我們嘗試使用operator char*()轉換,我們需要一個額外的構造函數隱式構造函數調用來使RHS成為一個string

這與string str1( expr ) ,其中expr不需要隱式轉換為string 可能必須轉換為初始化字符串構造函數的參數。 可能轉換的 expr直接初始化str1不是(n隱式)轉換本身,而只是函數調用。 沒有創建額外的臨時:

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

使用啟用的語言擴展進行編譯時第二個定義被拒絕。 沒有語言擴展,這種初始化在VS2013 Update 2中很好。


第三個遵循不同的初始化方案。 據我所知,在這種情況下它應該像第二個一樣。 似乎語言擴展似乎僅適用於第二個,但不適用於第三個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM