2015-12-17 62 views
0

爲了支持沒有explicit關鍵字的編譯器(例如MSVC 2012),我必須實現安全的bool慣用法。應該對bool進行檢查的類正在建模一個指向許多類的指針,因此它應該可以轉換爲這些指針。下面的代碼描述了一個思路:如果我們使用基於explicit operator bool()執行一切正常安全bool多次轉換歧義

// Uncomment this line to change implementation to 'safe bool' 
// #define _COMPILER_NO_EXPLICIT 

#if !defined(_COMPILER_NO_EXPLICIT) 
#define OPERATOR_BOOL_MYTYPE(...) 
#define OPERATOR_BOOL_IMPLEMENTATION(...) \ 
    public: \ 
      explicit operator bool() const noexcept \ 
      { \ 
        return __VA_ARGS__; \ 
      } 
#else 
#define OPERATOR_BOOL_MYTYPE(...) \ 
    private: \ 
      void safe_bool() {}; \ 
      typedef __VA_ARGS__ safe_bool_my_type_t; \ 
      typedef void (safe_bool_my_type_t::*safe_bool_t)() 

#define OPERATOR_BOOL_IMPLEMENTATION(...) \ 
    public: \ 
      operator safe_bool_t() const noexcept \ 
      { \ 
        return __VA_ARGS__ ? \ 
          &safe_bool_my_type_t::safe_bool : \ 
          nullptr; \ 
      } 
#endif 


class Convertible 
{ 
public: 
    operator int*() const 
    { return nullptr; } 

    operator double*() const 
    { return nullptr; } 

    OPERATOR_BOOL_MYTYPE(Convertible); 
    OPERATOR_BOOL_IMPLEMENTATION(false); 
}; 


int main(void) 
{ 
    Convertible a; 
    if (a) 
    { 
     // this 'if' statement introduces compilation error 
     // in 'safe bool' implementation 
    } 
    return 0; 
} 

。問題實際上是在基於「安全布爾」的實現中的模糊可轉換性。它應該如何解決?

注意:考慮布爾轉換實現獨立於其他指針轉換實現。如果不可能給我一個線索如何在相關情況下實現它,例如如果Convertible的計算結果爲true,如果其他轉換運算符之一正在返回非空值。

UPD:我相信有一種方法可以使一個隱式轉換比所有其他更優先。

+0

您是否考慮使用http://www.boost.org/doc/libs/master/libs/core/doc/html/core/explicit_operator_bool.html? – erenon

+0

是的,我回顧了升壓代碼。它實際上以相同的方式做事情,因此遭受同樣的問題:( – svv

回答

1

你是肯定你需要隱式轉換爲其他指針類型嗎?如果你不需要這個,問題就會消失。

如果您確實需要隱式轉換爲指針類型,則問題似乎沒有意義:您不需要轉換爲bool,因爲轉換爲指針也會產生可以進行真實測試的值(就像一個常規的原始指針)。

但由於您有int*double*的操作員,您仍然留下模糊的轉換。這部分可能需要重新設計,因爲目前尚不清楚如何將單個值隱式轉換爲多個不相關的指針類型。

+0

是的,這實際上是我的問題:) – svv

+0

@svv:你的意思是你的問題是你有一個根本上有缺陷的設計?好的,我們來修復它!怎麼樣,而不是隱式轉換爲各種指針類型,只有一個可能的指針類型?或者,有一個模板函數,調用者必須指定,例如'template T * as()'? –

+0

我不應該改變客戶端代碼,只有當方法被隱式使用時,我才能強制它使用新的方法。 – svv

0

其實沒有很好的解決方案。我發現一個部分符合我的要求,並管理其他要求削弱。

根據http://en.cppreference.com/w/cpp/language/implicit_cast設定和隱式轉換的順序如下:

1)零個或一個標準轉換序列

2)零個或一個用戶定義的轉換

3 )零個或一個標準轉換序列

作爲這兩種類型的轉換任務離子是用戶定義的,都允許進一步標準轉換爲bool我決定將operator int*()operator double*()轉換函數更改爲其他operator Ptr<int>()operator Ptr<double>其中Ptr<T>是一個模板類,其行爲與原始指針相同。特別是它可以轉換爲布爾,但這並不重要,因爲它是第二次用戶轉換,因此它被禁止。所以唯一轉換爲bool存在(這是從'安全布爾'實施)。

此解決方案的缺點是客戶端代碼需要更改接口或執行顯式強制轉換爲原始指針。