2009-12-23 44 views
2

我想設置一個靜態斷言(主要功能外)與GCC v4.3.x:無效靜態斷言行爲

#define STATIC_ASSERT(cond) extern void static_assert(int arg[(cond) ? 1 : -1]) 
STATIC_ASSERT((double)1 == (double)1); // failed 

但是當我使用浮點數,斷言總是失敗。

是否可以正確運行此靜態斷言?

回答

8

C++標準2003 5.19 「常量表達式」,第1款

In several places, C++ requires expressions that evaluate to an integral or enumeration constant: as array bounds (8.3.4, 5.3.4), as case expressions (6.4.2), as bit-field lengths (9.6), as enumerator initializers (7.2), as static member initializers (9.4.2), and as integral or enumeration non-type template arguments (14.3).

constant-expression: conditional-expression

An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type tem- plate parameters of integral or enumeration types, and sizeof expressions. Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types. Only type conversions to integral or enumeration types can be used. In particular, except in sizeof expressions, functions, class objects, pointers, or references shall not be used, and assignment, increment, decrement, function-call, or comma operators shall not be used.

+1

但是爲什麼?爲什麼這是一個限制?那有什麼意義? – shoosh 2010-05-29 17:50:56

+0

我不知道。恕我直言,因爲浮動操作不準確。 – 2010-06-01 13:08:59

2

編輯:

實際上,移動STATIC_ASSERTmain()給出了一個編譯器錯誤,因爲流延到不是整型或枚舉類型之外的類型不能在常量表達式出現。使用GCC刪除演員陣容仍然不是有效的ICE(正如@AndreyT指出的那樣)。

#define STATIC_ASSERT(cond) extern void static_assert(int arg[(cond) ? 1 : -1]) 

STATIC_ASSERT(1.0 == 1.0); 
STATIC_ASSERT(1.0 != 1.0); // this is line 4 

int main() 
{ 
    return 0; 
} 

給出:

main.cpp:4: error: size of array ‘arg’ is negative

Reference: ISO/IEC 14882 - 5.19 Constant Expressions

An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, andsizeofexpressions. Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types. Only type conversions to integral or enumeration types can be used. In particular, except in sizeof expressions, functions, class objects, pointers, or references shall not be used, and assignment, increment, decrement, function-call, or comma operators shall not be used.


EDIT2:備案,這是我自己實現從我的代碼庫中提取靜態斷言的:1951741.cpp

#define CONCATENATE(arg1, arg2) CONCATENATE1(arg1, arg2) 
#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2) 
#define CONCATENATE2(arg1, arg2) arg1##arg2 

/** 
* Usage: 
* 
* <code>STATIC_ASSERT(expression, message)</code> 
* 
* When the static assertion test fails, a compiler error message that somehow 
* contains the "STATIC_ASSERTION_FAILED_AT_LINE_xxx_message" is generated. 
* 
* /!\ message has to be a valid C++ identifier, that is to say it must not 
* contain space characters, cannot start with a digit, etc. 
* 
* STATIC_ASSERT(true, this_message_will_never_be_displayed); 
*/ 

#define STATIC_ASSERT(expression, message)\ 
    struct CONCATENATE(__static_assertion_at_line_, __LINE__)\ 
    {\ 
    implementation::StaticAssertion<static_cast<bool>((expression))> CONCATENATE(CONCATENATE(CONCATENATE(STATIC_ASSERTION_FAILED_AT_LINE_, __LINE__), _), message);\ 
    };\ 
    typedef implementation::StaticAssertionTest<sizeof(CONCATENATE(__static_assertion_at_line_, __LINE__))> CONCATENATE(__static_assertion_test_at_line_, __LINE__) 

    // note that we wrap the non existing type inside a struct to avoid warning 
    // messages about unused variables when static assertions are used at function 
    // scope 
    // the use of sizeof makes sure the assertion error is not ignored by SFINAE 

namespace implementation { 

    template <bool> 
    struct StaticAssertion; 

    template <> 
    struct StaticAssertion<true> 
    { 
    }; // StaticAssertion<true> 

    template<int i> 
    struct StaticAssertionTest 
    { 
    }; // StaticAssertionTest<int> 

} // namespace implementation 


STATIC_ASSERT(1.0f == 1.0 , ok); 
STATIC_ASSERT(1.0f != 1.0 , ko); 

int main() 
{ 
    return 0; 
} 

當使用STATIC_ASSERT((float) 1 == (float) 1, must_be_true);它給出了一個適當的錯誤:

main.cpp:49: error: a cast to a type other than an integral or enumeration type cannot appear in a constant-expression


剛纔你的問題是什麼?

#define STATIC_ASSERT(cond) extern void static_assert(int arg[(cond) ? 1 : -1]) 

int main() 
{ 
    STATIC_ASSERT((float)1 == (float)1); 
    STATIC_ASSERT((float)1 != (float)1); // this is line 6 
    return 0; 
} 

用gcc 4.4.2編譯它給了我:

main.cpp: In function ‘int main()’:

main.cpp:6: error: size of array ‘arg’ is negative

所以,是的,(float)1 != (float)1計算結果爲false,使您的STATIC_ASSERT宏使用尺寸-1數組,它停止編譯。

+0

嘗試確實移動STATIC_ASSERT(...)外的main() – 2009-12-23 10:04:20

+0

,主要的'外移動它( )'給出了一個編譯器錯誤 – 2009-12-23 10:25:54

+1

我編輯了一個鏈接到一個STATIC_ASSERT實現的答案,它給出了關於在常量表達式中鑄造的正確的編譯器錯誤信息 – 2009-12-23 10:57:51

4

我認爲這與規則有關,除了整數或枚舉類型之外,不能出現在常量表達式中。

// would all work for example 
STATIC_ASSERT(1.0 == 1.0); 
STATIC_ASSERT((int)1.0 == (int)1.0); 

所以它不是斷言本身是無效的,並導致編譯器錯誤,這是你的投...

只是爲了記錄在案,升壓,當然,有一個static assert了。