2015-03-31 63 views
0

正如我的previous question我想建立一個條件來檢查兩種類型檢查是否應該dynamic_cast或不。 我以下條件:爲什麼這些條件不適用於模板類型?

#define can_dynamic_cast(FROM, TO) \ 
           can_cast(FROM, TO) && \ 
           !std::is_same<FROM, TO>::value && \ 
           std::is_class<TO>::value && \ 
           !std::is_const<FROM>::value && \ 
           std::is_base_of<TO, FROM>::value 

它不低於基本檢查工作,can_dynamic_cast將返回true!

static_assert(!can_dynamic_cast(int, int), "didn't expecting dynamic cast, but could!") 

出於絕望,我回到了低於條件,但仍然沒有希望!

#define can_dynamic_cast(FROM, TO) \ 
            std::is_convertible<FROM, TO>::value && \ 
            std::is_class<TO>::value && \ 
            std::is_class<FROM>::value 

上述條件是最基本的條件,can_dynamic_cast將再次返回true(int, int),這不是假設!

問題

1)我什麼都沒有錯?

+6

嘗試手動擴展您的宏。提示:'!'沒有被應用到整個表達式。 – 2015-03-31 17:44:04

+0

@Brian但是目標類型必須是一個指向/完整類類型的指針或引用,或者指向cv void的指針。 – 2015-03-31 17:45:16

+0

@ T.C。哎呀,你是對的。我錯過了。 – Brian 2015-03-31 17:47:40

回答

0

綜上所述在評論中給出的解決方案和答案:(感謝T.C.和AntonSavin)

您的宏並不完全錯,但它是一個宏。預處理簡單地替換宏的內容宏調用:

static_assert(!can_dynamic_cast(int, int), "..."); 
// => 
static_assert(!std::is_convertible<int, int>::value && 
       std::is_class<int>::value && 
       std::is_class<int>::value , "..."); 

因此,只有第一個值被否定而這將產生意外的行爲。

爲了克服這個問題,你必須加上括號,無論是在宏觀的定義,或在宏的號召:

#define can_dynamic_cast(FROM, TO) \ 
     (std::is_convertible<FROM, TO>::value && \ 
      std::is_class<TO>::value && \ 
      std::is_class<FROM>::value) 
// or 

static_assert(!(can_dynamic_cast(int, int)), "..."); 

更好的解決方案,而不是更長的解決方案是建立一個自己的類型-traits類:

template <class FROM, class TO> 
struct can_dynamic_cast : std::integral_constant< bool, 
    std::is_convertible<FROM, TO>::value && 
    std::is_class<TO>::value && 
    std::is_class<FROM>::value > {}; 

static_assert(!can_dynamic_cast<int, int>::value, "..."); 

它是容易出錯的更小,因爲它遵循C++語法在元函數的調用和不需要附加的支架。

相關問題