无效静态断言行为

问题描述:

我想设置一个静态断言(主要功能外)与GCC v4.3.x:无效静态断言行为

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

但是当我使用浮点数,断言总是失败。

是否可以正确运行此静态断言?

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

编辑:

实际上,移动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

我认为这与规则有关,除了整数或枚举类型之外,不能出现在常量表达式中。

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

所以它不是断言本身是无效的,并导致编译器错误,这是你的投...

只是为了记录在案,升压,当然,有一个static assert了。