7

考慮T的下面的構造函數:問題與構造解析順序

struct T { 
    T(const bool) { std::cout << "T(const bool)" << endl; } 
    T(const std::string&) { std::cout << "T(const std::string&)" << endl; } 
}; 

T t(""); 
  1. 構建T當爲什麼T(const bool)優先T(const std::string&)
  2. 由於上述優先級可能會導致希望調用T(const std::string&)的用戶感到困惑,因此在將字符串文字傳遞給T的構造函數時,我可以做些什麼來隱式調用T(const std::string&)。現在我發現的唯一工作就是添加另一個構造,這需要最高優先級:

    T(const char* s) 
    { 
        std::cout << "T(const char*)" << endl; 
        *this = std::string(s); 
    } 
    
  3. 除了上述解決方案,宣佈explicit T(const bool)避免混淆不解決上述問題:在這種情況下,雖然T t = ""現在禁止,爲什麼是形式T t("")仍然被允許並確實打電話給T(const bool)

回答

8

構建t時爲什麼T(const bool)接管T(const std::string&)優先?

""char[1]類型;這可以通過數組到指針的轉換隱式轉換爲char const*。指針可隱式轉換爲bool,所有非空指針變爲true,並且所有空指針變爲false。這些都是「內置」標準轉換。

char const* -> std::string轉換是用戶聲明的轉換:它使用std::string的轉換構造函數,該轉換構造函數需要char const*

標準(「內置」)的轉換優於重載期間用戶聲明的轉換,因此構造採取bool是更好的匹配比一個服用std::string這裏。

目前唯一的解決辦法,我發現是添加另一個構造

這聽起來像一個合理的解決方案;無疑是您描述的簡單場景最直接的解決方案。儘管如此,您使用*this的作業有點笨拙;將兩個構造函數委託給一些初始化函數會更好。

或者,你可以使用帶有enable_if任何構造一個模板,你想禁止轉換:

template <typename U> 
T(U, std::enable_if<std::is_same<U, bool>::value>::type* = 0) { } 

此構造將只調用了bool說法而已。您可以在Boost,C++ TR1或C++ 0x中找到enable_ifis_same。您也可以使用!is_pointer,is_integral或某些其他類型特徵組合來允許其他參數類型,但不允許使用char const*

或者作爲另一種選擇,你可能完全避開bool和對應於truefalse的構造統計員使用自己的枚舉。這是否合理取決於您的使用情況。

聲明explicit T(const bool)以避免不能解決上述問題...爲什麼表格T t("")仍然被允許並且確實調用T(const bool)

explicit僅禁止將隱式轉換爲TT t("");根本沒有轉換爲T;它通過將參數""傳遞給哪個構造函數匹配得最好來直接初始化對象t

+0

非常感謝解決方案模板 – pipex

+0

'enable_if'應該以'... :: type * = 0'結尾。 – UncleBens

+0

@UncleBens:非常感謝。固定。 –

1

""可以轉換爲std::stringbool

問題是,它會轉換哪種方式?

  • 轉換爲std::string是用戶定義的轉換。
  • 轉換爲bool是標準轉換。

所以答案是,標準轉換比用戶定義的轉換具有更高的優先級。所以""將轉換爲bool

實施例,

struct A 
{ 
    A(int i) {} //i.e an int can implicity convert to A 
}; 

void f(const A &) { cout << "User-defined conversion won" << endl; } 
void f(const bool &) { cout << "Standard conversion won" << endl; } 

int main() { 
     f (10); 
     return 0; 
} 

輸出:

Standard conversion won 

在線演示:http://www.ideone.com/5Bt0K

在上述演示,10可以轉換到Abool兩者。由於轉換爲bool是標準轉換,因此它將轉換爲bool,而不是A

0

因爲如果內置的轉換器可用,則不考慮用戶定義的轉換。

使用第三個構造函數,其中一個需要const char*。沒有更好的辦法。

+0

「沒有更好的辦法。」我不敢苟同。 –

+0

@James McNellis:你的'enable_if'方法的確看起來不錯。 –