C++ 编译时断言?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6765770/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Compile-time assertion?
提问by Jason S
Is there a way I can assert that two constant expressions are equal at compile time?
有没有办法可以断言两个常量表达式在编译时相等?
e.g. I want this to cause a compile-time error
例如,我希望这会导致编译时错误
enum { foo=263, bar=264 };
SOME_EXPRESSION(foo,bar)
but I want this to not cause an error
但我希望这不会导致错误
enum { foo=263, bar=263 };
SOME_EXPRESSION(foo,bar)
edit: the above was simplified. My situation is more like
编辑:以上已简化。我的情况更像是
some_other_file_I_dont_control.h:
some_other_file_I_dont_control.h:
class X
{
public:
enum { foo=263 };
}
my_file.h:
my_file.h:
enum { bar=something+somethingelse }; // bar should equal X::foo
SOME_EXPRESSION(X::foo, bar)
采纳答案by user541686
See static_assert
(C++0x only); if on an older version, see Boost's StaticAssert
.
请参阅static_assert
(仅限 C++0x);如果在旧版本上,请参阅Boost 的StaticAssert
.
回答by Chad
Yes. You can do this with template specializations on type bool, like this:
是的。您可以使用 bool 类型的模板特化来做到这一点,如下所示:
// empty default template
template <bool b>
struct StaticAssert {};
// template specialized on true
template <>
struct StaticAssert<true>
{
static void assert() {}
};
int f()
{
StaticAssert<1==1>::assert(); // compiles fine, assert() member found
StaticAssert<1==2>::assert(); // compile failure, no assert() member for StaticAssert<false>
}
Code is basically from memory, may need some tweaks.
代码基本上来自记忆,可能需要一些调整。
回答by David Rodríguez - dribeas
For another version of a static assert, that you can glorify by adding a better name, you can use:
对于静态断言的另一个版本,您可以通过添加更好的名称来美化,您可以使用:
// name must be a valid identifier
#define STATIC_ASSERT( condition, name )\
typedef char assert_failed_ ## name [ (condition) ? 1 : -1 ];
And use as:
并用作:
STATIC_ASSERT( x == y, constants_must_be_same );
The compiler will trigger an error similar to:
编译器将触发类似于以下内容的错误:
size of array 'assert_failed_constants_must_be_same' is negative
Which does not seem that helpful, but it will point to the exact line of the assert, and after a while you will start processing that error message as static assert failed
这似乎没有帮助,但它会指向断言的确切行,一段时间后您将开始处理该错误消息,因为静态断言失败
回答by Benjamin Herreid
回答by epatel
There is also the trick to use a switch (..)
statement. Kind of old style though. The case entry foo == bar has to be compile time evaluated and if it happens to be false the switch statement will cause an error. The compiler will also reduce it to "nothing".
还有使用switch (..)
语句的技巧。虽然有点老式。case 条目 foo == bar 必须在编译时进行评估,如果它恰好为 false,则 switch 语句将导致错误。编译器也会将其减少为“无”。
{
bool x=false;
switch (x) {
case foo == bar:
break;
case false:
// Compile time test that foo == bar
break;
}
回答by Dhia Hassen
you can define your own static assertion , this way :
您可以通过这种方式定义自己的静态断言:
#include <iostream>
template <bool b> class ClassStaticAssert;
template <>
class ClassStaticAssert<true>{static const bool value = true;};
#define STATIC_ASSERT(e) (ClassStaticAssert<e>())
int main()
{
STATIC_ASSERT(0);
return 0;
}
回答by Andreas Spindler
template <int a, int b>
inline void static_assert_equal()
{
typedef char enum_values_must_be_equal[a == b ? 1 : -1];
(void) sizeof(enum_values_must_be_equal);
}
int main()
{
enum { foo = 1, bar = 2, fum = foo };
static_assert_equal<foo, fum>(); // compiles ok
static_assert_equal<foo, bar>(); // fails at compile time
return 0;
}
This derives from the checked_delete
idiom.
这源自于checked_delete
成语。
回答by Dodgie
Similar to iammillind's solution, which was unfortunately one only useful at runtime:
类似于 iammillind 的解决方案,不幸的是,它只在运行时有用:
template <int A, int B>
class VALUES {
};
// specialization to provide safe passage for equal values
template <int X>
class VALUES<X, X> {
public:
static void MY_VALUES_ARE_EQUAL() {}
};
#define ASSERT_EQUALITY(a, b) \
{ \
typedef VALUES<a, b> COMPILE_TIME_ASSERTION; \
COMPILE_TIME_ASSERTION::VALUES_ARE_EQUAL(); \
}
int main() {
ASSERT_EQUALITY(1, 1); // compiles just fine
ASSERT_EQUALITY(1, 2); // ERROR!
// . . .
}
The nice thing about this is that it provides a nice compiler message. My compiler tells me the following:
这样做的好处是它提供了一个很好的编译器消息。我的编译器告诉我以下内容:
‘VALUES_ARE_EQUAL' is not a member of ‘COMPILE_TIME_ASSERTION {aka VALUES<1, 2>}'
'VALUES_ARE_EQUAL' 不是 'COMPILE_TIME_ASSERTION {aka VALUES<1, 2>}' 的成员
You don't need the typedef. Without:
你不需要 typedef。没有:
'VALUES_ARE_EQUAL' is not a member of 'VALUES<1, 2>'
“VALUES_ARE_EQUAL”不是“VALUES<1, 2>”的成员
Of course, there are a bunch of other ways to generate helpful messages. For giggles:
当然,还有很多其他方法可以生成有用的消息。对于笑声:
// these give use some tips in the compiler warnings
class COMPILE_TIME_EQUALITY_ASSERTION {} compiler_message;
class EQUAL_VALUES_ONLY_PLEASE {};
template <int A, int B>
class VALUES {
public:
static void AreEqual(EQUAL_VALUES_ONLY_PLEASE) {}
};
template <int X>
class VALUES<X, X>
{
public:
static void AreEqual(COMPILE_TIME_EQUALITY_ASSERTION) {}
};
#define ASSERT_EQUALITY(a, b) \
{ \
VALUES<a, b>::AreEqual(compiler_message); \
}
int main() {
ASSERT_EQUALITY(1, 1) // a-okay
ASSERT_EQUALITY(1, 2) // ERROR!
}
I get the following compiler errors:
我收到以下编译器错误:
no matching function for call to:
‘VALUES<1,2>::AreEqual(COMPILE_TIME_EQUALITY_ASSERTION&)'
candidate is:
static void VALUES<\A, B>::AreEqual(EQUAL_VALUES_ONLY_PLEASE) [with int A = 1, int B = 2]
combinations of static member functions/constructors/field assignment/privacy and template specifications can yield different results perhaps more appropriate for your situation.
静态成员函数/构造函数/字段分配/隐私和模板规范的组合可以产生不同的结果,也许更适合您的情况。
回答by linello
I suggest to take a look at the Eigen library static assert mechanism:
我建议看一下 Eigen 库静态断言机制:
回答by marc
You can do some preprocessor magic like
你可以做一些预处理魔法,比如
#define FOO_VALUE 263
#define BAR_VALUE 264
enum {foo=FOO_VALUE, bar=BAR_VALUE}
#if !(FOO_VALUE == BAR_VALUE)
#error "Not equal"
#endif