2017-01-19 103 views
0

假設我有一個這樣的宏:的static_cast <T> VS T(N)的基本類型

#define IS_SIGNED_B(T) (static_cast<T>(-1)<0) 

難道是正常的把它寫爲

#define IS_SIGNED_B(T) (T(-1)<0) 

知道T是(應該是)永遠是一個基本類型。還有其他一些我需要明確某種特定價值的情況。

我知道這可能會導致問題,對於像情形:

signed char(0); 

但知道我已經基本類型Typedef的爲:

typedef signed char Int8; 
Int8(0); 

是否有比這以外的任何其他問題?基礎類型的構造函數可以被認爲與靜態類型相同嗎?

編輯:我知道std::numeric_limitsstd::is_signed的存在。這只是一個例子。不是實際的情況。我很抱歉沒有提到這一點。

+2

就我個人而言,我會避免所有這些和我們['std :: numeric_limits :: is_signed'](http://en.cppreference.com/w/cpp/types/numeric_limits/is_signed) – NathanOliver

+2

爲什麼你需要一個當['std :: is_signed'](http://en.cppreference.com/w/cpp/types/is_signed)存在時爲此宏? – Borgleader

+0

你似乎認爲'T(-1)'爲'T == int'調用'T'的構造函數,然而,這只是c風格演員的替代語法,可能被實現爲'static_cast',所以應該沒有區別。 – nwp

回答

3

基本類型的構造函數可以被認爲與靜態類型相同嗎?

基本類型沒有構造函數。 Int8(0)(Int8)0的顯式類型轉換和替代語法。這就是所謂的C風格演員。另一種語法稱爲功能性表達式。

對於基本整數類型,C風格轉換相當於static_cast。但總的來說它並不相同。如果沒有static_cast可用,那麼它將執行reinterpret_cast(或const_cast,或const_cast和其他類型轉換之一)的組合。

除此之外還有其他問題嗎?

我不太明白你提出了什麼問題,但是明確的類型轉換確實有很大的問題。主要問題是程序員不完美,你不能認爲T is (should) always be a fundamental type總是成立。你希望編譯器能夠抓住這樣的錯誤。 C風格演員將隱藏您或您的同事可能犯的一些錯誤,並用未定義的行爲替換錯誤消息。

也許在你的宏的上下文中,沒有定義的行爲幾乎沒有危險,但正如你所說,這只是一個例子。一個好的經驗法則:更喜歡使用你想要的* _cast的確切類型,而不是讓C風格的演員選擇一個可能不是你想要的演員陣容。

+0

謝謝。這一切我想知道。它是否可以被認爲是一個靜態演員或C型演員。這一直在困擾着我一段時間,我想我忘記了需要對此有清楚理解的情況。我很抱歉沒有正確地提出問題。 –

1

你應該做的第一件事是停止不必要地使用C預處理器。

只需使用std::is_signed

做不到這一點,是這樣的:

template<class T> 
constexpr 
std::integral_constant<bool, 
    (static_cast<T>(-1)<0) 
> is_signed_b() { return {}; } 

這是您的宏的一個工業強度的版本。

它返回一個空類,它有一個constexpr conversion-to-bool,它的值是你想要的結果。它可以在編譯時進行評估(事實上,它很難)。


但是你的宏有什麼問題?

首先,您的宏應該閱讀:

#define IS_SIGNED_B(...) (static_cast<__VA_ARGS__>(-1)<0) 

因爲

IS_SIGNED_B(std::tuple_element_t<some_tuple, Is>)... 

與實施不必要的中斷。

C預處理器不理解C++。它不知道,不再包含在(){}中。

如上所述,如果T是雙字類型,則代碼會中斷。

另一個問題是,如果你餵它一個類型,不是一個整數類型,奇怪的事情可能會發生。 C風格的強制轉換是強大的,並且可以用於指針類型。所以你會在左邊得到指針類型值-1。在右邊,你會得到0,它隱含地轉換爲任何指針類型的空值。然後比較東西。本段包含各種未定義的行爲。