无效的静态断言行为

我正在尝试使用GCC v4.3.x设置静态断言(在main函数之外):

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

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

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

C ++ Standard 2003,5.19“常量表达式” ,第1段。

在一些地方,C ++要求表达式计算为整数或枚举常量: 作为数组边界(8.3.4,5.3.4) ,作为案例表达式(6.4.2),作为位字段长度(9.6),作为枚举器初始化器(7.2),作为静态成员初始值设定项(9.4.2),以及作为整数或枚举非类型模板参数(14.3)。

constant-expression:条件表达式

一个整数常量表达式只能包含文字(2.13),枚举数,常量变量或用常量表达式(8.5)初始化的整数或枚举类型的静态数据成员,整数或枚举类型的非类型模板参数,以及sizeof表达式。 浮动文字(2.13.3)只有在转换为整数或枚举类型时才会出现。 只能使用转换为整数或枚举类型的转换。 特别是,除了sizeof表达式之外,不应使用函数,类对象,指针或引用,并且不应使用赋值,递增,递减,函数调用或逗号运算符。

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

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

所以这不是断言本身无效,并导致编译错误,这是你的演员……

只是为了记录,当然,提升也有一个静态断言 。

编辑:

实际上,将STATIC_ASSERT移出main()会产生编译器错误,因为对整数或枚举类型以外的类型的STATIC_ASSERT不能出现在常量表达式中。 删除演员表与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:错误:数组’arg’的大小为负数

参考:ISO / IEC 14882 – 5.19常数表达式

整数常量表达式只能涉及文字(2.13),枚举数, const变量或使用常量表达式(8.5)初始化的整数或枚举类型的static数据成员,整数或枚举类型的非类型模板参数,以及表达式大小。 浮动文字(2.13.3)只有在转换为整数或枚举类型时才会出现。 只能使用转换为整数或枚举类型的转换。 特别是,除了sizeof表达式之外,不应使用函数,类对象,指针或引用,并且不应使用赋值,递增,递减,函数调用或逗号运算符。


EDIT2:对于记录,这是我自己的代码库中提取的静态断言的实现: 1951741.cpp

 #define CONCATENATE(arg1, arg2) CONCATENATE1(arg1, arg2) #define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2) #define CONCATENATE2(arg1, arg2) arg1##arg2 /** * Usage: * * STATIC_ASSERT(expression, message) * * 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((expression))> CONCATENATE(CONCATENATE(CONCATENATE(STATIC_ASSERTION_FAILED_AT_LINE_, __LINE__), _), message);\ };\ typedef implementation::StaticAssertionTest 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  struct StaticAssertion; template <> struct StaticAssertion { }; // StaticAssertion template struct StaticAssertionTest { }; // StaticAssertionTest } // 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:错误:转换为整数或枚举类型以外的类型不能出现在常量表达式中


你的问题到底是什么?

 #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:在函数’int main()’中:

main.cpp:6:错误:数组’arg’的大小为负数

所以是的, (float)1 != (float)1计算结果为false ,并使你的STATIC_ASSERT宏使用一个大小为-1的数组来停止编译。