9

我還有一個問題涉及到安全布爾成語:常量,正確性和安全布爾成語

typedef void (Testable::*bool_type)() const;    // const necessary? 
void this_type_does_not_support_comparisons() const {} // const necessary? 

operator bool_type() const 
{ 
    return ok_ ? &Testable::this_type_does_not_support_comparisons : 0; 
} 

怎麼來的bool_type(typedef的)和this_type_does_not_support_comparisonsconst? 實際上沒有人應該通過返回指針調用成員函數吧? 這裏需要const嗎? operator bool_type(成員函數)否則會違反const正確性?

+0

我敢打賭,'const'是沒有必要的。函數的主體也不是,因爲無論如何你都不應該調用函數。 –

+0

@Alex:但是沒有body的成員函數沒有地址,對吧?至少在沒有VC10的機構的情況下,它是無法編譯的。 – fredoverflow

+0

嗯你是對的。我剛剛檢查過我的VS2005當前項目中的'safe_bool'模板,它有一個主體。它也有'const'。 –

回答

5

「安全布爾成語」是對「我想要一輛既是跑車又是拖拉機,也許是一條船」的問題的技術答案。實際的答案不是技術答案。

這就是說,它解決了問題,只是給結果,該結果轉換爲bool而不是別的東西也不多(否則類的一個實例可以爲其中例如在正式的說法是int實際參數傳遞,說)。數據指針可以轉換爲void*。函數指針不是,至少在C++標準中是正式的(Posix是別的,也是練習)。

使用成員函數指針防止意外地調用該函數,只要給定safe bool操作符的指針即可。const收斂了一點,但如果命運讓某人犯了最大數量的愚蠢錯誤,那麼這個人仍然可以設法稱之爲無所事事功能。而不是const我想我會讓它有一個私人類型的參數,其他代碼不能提供這樣的參數,然後它不必是一個愚蠢的成員函數類型了。

可以是這樣的:

#include <stdio.h> 

class Foo 
{ 
private: 
    enum PrivateArg {}; 
    typedef void (*SafeBool)(PrivateArg); 
    static void safeTrue(PrivateArg) {} 

    bool state_; 

public: 
    Foo(bool state): state_(state) {} 

    operator SafeBool() const 
    { return (state_? &safeTrue : 0); } 
}; 

int main() 
{ 
    if(Foo(true)) { printf("true\n"); } 
    if(Foo(false)) { printf("false\n"); } // No output. 

    //int const x1 = Foo(false);  // No compilado! 
    //void* const x2 = Foo(false);  // No compilado! 
} 

當然,實際的答案是不是這樣的:

#include <stdio.h> 

class Foo 
{ 
private: 
    bool isEmpty_; 

public: 
    Foo(bool asInitiallyEmpty) 
     : isEmpty_(asInitiallyEmpty) 
    {} 

    bool isEmpty() const { return isEmpty_; } 
}; 

int main() 
{ 
    if(Foo(true).isEmpty()) { printf("true\n"); } 
    if(Foo(false).isEmpty()) { printf("false\n"); } // No output. 

    //bool const x0 = Foo(false);  // No compilado! 
    //int const x1 = Foo(false);  // No compilado! 
    //void* const x2 = Foo(false);  // No compilado! 
} 

摘要WRT。提問:

  • bool_type(typedef)和this_type_does_not_support_comparisons是怎麼來的?

有人不太明白他們編碼。或者也許是他們打算限制一下通話的能力。但是,那是非常徒勞的措施。

  • 沒有人應該通過返回指針實際調用成員函數,對吧?

沒錯。

  • 在這裏常量是必要的嗎?

  • 將運營商bool_type(成員函數)違反常量,正確性,否則?

乾杯&心連心,

+0

「我想我只是讓它有一個私人類型的論點」,哦,等等,我收回我以前的發言,這太棒了! – fredoverflow

+0

我寫了一些關於'const'的錯誤,以某種方式混淆黑白。我只是把它展示出來。對不起 - 其餘的確定。 –

+0

您仍然可以(愚蠢地,但這是練習的要點)聲明一個帶有簽名'void(Foo :: PrivateArg)'的免費函數,並將它與'operator SafeBool'的結果進行比較。畢竟,我認爲'SafeBool'類型必須是一個指向成員函數的指針。 –

1

8.3.5/A CV-限定符-SEQ應僅是功能類型的一部分 一個非靜態成員函數中,向其中一個指針 構件是指功能類型,或頂層功能型一個函數typedef 聲明。函數聲明器 中的cv-qualifier-seq的作用與在函數 類型的頂部添加cv-qualification不同,即它不會創建cv限定的函數類型。

如果我正確讀取,你可以一個const成員函數返回一個指向非const成員。你只是不能用非const對象來調用它。

禁止調用的一種方式是:

private: 
    struct private_ 
    { 
     void this_type_does_not_support_comparisons() {} 
    }; 

public: 
    typedef void (private_::*bool_type)() const; 

    operator bool_type() const 
    { 
     return ok_ ? &private_::this_type_does_not_support_comparisons : 0; 
    } 

指針成員函數仍可以進行相等比較。您必須針對觸發錯誤的Testable::bool_type類型編寫operator==operator!=。使用安全布爾方式的CRTP形式更容易,因爲這些運營商成爲模板,因此可能有錯誤的身體。

例子:

template <typename T> 
class safe_bool_concept 
{ 
    // Implementation detail of safe bool 
protected: 
    ~safe_bool_concept() {} 

public: 
    operator safe_bool() const 
    { 
     return static_cast<const T*>(this)->is_null() ? ...; 
    } 
}; 

struct Foo : safe_bool_concept<Foo> 
{ 
    ... 

private: 
    friend class safe_bool_concept<Foo>; 
    bool is_null() const { ... } 
}; 

那麼你可以做(​​做同樣的!=):

template <typename T> 
void operator==(const safe_bool_concept<T>& x, const safe_bool_concept<T>&) 
{ 
    x.some_private_member(); // invalid, but won't be generated 
          // unless safe_bool classes are compared 
} 

這意味着安全布爾成語應通過CRTP如果你想禁止的比較來實現。然而,比較爲零仍然有效。

如果你走非會員功能路線,你將不得不提供<,>,<=>=

+0

@Alf:讓我寫一些代碼,使我的意圖更清晰。 –