2010-02-19 109 views
4

運算符bool()如何在類中聲明運算符std :: string時導致錯誤,還可以作爲隱式轉換字符串本身?運算符bool()轉換爲std :: string並與運算符衝突std :: string()

#include <iostream> 
#include <string> 
using namespace std; 

class Test { 
public: 
    operator std::string() { cout << "op string" << endl; return "whatever";} 
    operator bool() { cout << "op bool" << endl; return true;} 
}; 

int main(int argc, char *argv[]) { 
    string s; 
    Test t; 
    s = t; 
} 
+2

如果你打算繼續'使用命名空間標準;'你爲什麼要繼續澄清'std :: string'? – 2010-02-19 08:33:21

回答

8

你面臨的問題(除了operator std::string()返回一個布爾值)是隱式轉換觸發,當你想要和當你不需要。

當編譯器看到s = t它確定了以下潛在std::operator=比賽:

// using std::string for compactness instead of the full template 
std::string::operator=(std::string const &); 
std::string::operator=(char); 

現在,t既不是他們的,所以它試圖轉換的東西,可以適應,發現兩條路徑:轉換爲可以升級到char或直接轉換爲std::string的bool。編譯器不能真正決定並放棄。

這是您希望避免提供許多不同轉換運算符的原因之一。任何可以被編譯器隱式調用的東西最終都會在你認爲不應該的時候調用。

這個article專門處理這個問題。該建議是,而不是提供一個轉換到bool,提供一個轉換到一個成員函數

class testable { 
    typedef void (testable::*bool_type)(); 
    void auxiliar_function_for_true_value() {} 
public: 
    operator bool_type() const { 
     return condition() ? &testable::auxiliar_function_for_true_value : 0; 
    } 
    bool condition() const; 
}; 

如果這個類的一個實例是一個條件(if (testable()))編譯器會嘗試,並轉換爲bool_type,可以是內部使用在條件下使用。

編輯

的代碼是如何與這個解決方案更加複雜的評論後,可以隨時爲它作爲一個普通的小工具。一旦你提供了代碼的第一部分,複雜性就被封裝在頭文件中。

// utility header safe_bool.hpp 
class safe_bool_t; 
typedef void (safe_bool_t::*bool_type)(); 
inline bool_type safe_bool(bool); 

class safe_bool_t { 
    void auxiliar_function_for_true_value() {} 
    friend bool_type safe_bool(bool); 
}; 
inline bool_type safe_bool(bool) 
{ 
    return condition ? &safe_bool_t::auxiliar_function_for_true_value : 0; 
} 

你的類現在變得更加簡單,而且它本身就是可讀(通過爲功能和類型選擇合適的名稱):

// each class with conversion 
class testable { 
public: 
    operator bool_type() { 
     return safe_bool(true); 
    } 
}; 

只有當讀者想知道如何safe_bool成語實現並讀取它們填充的頭部將面臨的複雜性(可在註釋中解釋)

+0

提到safe_bool成語的問題無關。大多數情況下,你並不是真的想要一個布爾值,你只是想寫'if' test :) – 2010-02-19 09:13:28

+0

我假設bool正在通過整數提升轉換爲char,因爲標準沒有提到任何關於布爾轉換爲char。 引用:「一個bool類型的右值可以轉換爲int類型的右值,其中false爲零且真正成爲一個。」 – piotr 2010-02-19 09:36:12

+0

非常有趣的文章,但我發現它使用這樣的代碼如果測試,如果它是非常不可讀的,它打敗了添加可讀性的目的。另外輔助函數應該是const。 – piotr 2010-02-19 10:20:33

4

您的運算符std :: string()需要返回一個字符串,而不是bool。

+0

它返回一個字符串'std :: string(static_cast (true))' – MSalters 2010-02-19 08:42:22

+0

修正了錯字,但與 – piotr 2010-02-19 09:01:08

1

正如David Rodriguez正確指出的那樣,可以將bool升級爲char a nd你得到一個ambigous超載。

在stl中,通常通過轉換爲void *來完成類的可測試,例如,當你做

while (istream.getline()) { 
} 

循環條件解析爲false,因爲istream的,在它的operator void*返回NULL。

有些人認爲這不是一個解決方案,從理論上說好一個可以做

void* streamptr = istream; 
delete streamptr; 

但在我看來,如果有人開始刪除這樣的三分球......他不應該被允許任何接近stl代碼(或C++)的地方。

相關問題