没有提升的BOOST_STATIC_ASSERT

Kon*_*tin 23 c++ boost replace static-assert

由于在我工作的公司中禁止使用boost,我需要在纯C++中实现其功能.我已经研究了增强源,但它们似乎太复杂了,至少对我而言.我知道static_assert()在C++ 0x标准中有一些东西,但我不想使用任何C++ 0x功能.

APr*_*mer 24

另一个技巧(可以在C中使用)是尝试构建一个负数大小的数组,如果断言失败:

#define ASSERT(cond) int foo[(cond) ? 1 : -1]
Run Code Online (Sandbox Code Playgroud)

作为奖励,您可以使用typedef而不是对象,以便它可以在更多上下文中使用,并且在成功时不会发生:

#define ASSERT(cond) typedef int foo[(cond) ? 1 : -1]
Run Code Online (Sandbox Code Playgroud)

最后,建立一个名称冲突的可能性较小的名称(并且至少可以在不同的行中重用):

#define CAT_(a, b) a ## b
#define CAT(a, b) CAT_(a, b)
#define ASSERT(cond) typedef int CAT(AsSeRt, __LINE__)[(cond) ? 1 : -1]
Run Code Online (Sandbox Code Playgroud)

  • 如果你不这样做,那么宏的参数(比如`__LINE__`)就不会被扩展.所以它会生成`AsSeRt__LINE__`而不是想要的'AsSeRt42`.我很确定在某个地方有一个问题可以详细解释. (6认同)

Ale*_*tov 21

template<bool> struct StaticAssert;
template<> struct StaticAssert<true> {};

int main() {
   StaticAssert< (4>3) >(); //OK
   StaticAssert< (2+2==5) >(); //ERROR
}
Run Code Online (Sandbox Code Playgroud)

  • @Gregory:`typedef StaticAssert <(2 + 2 == 5)> AssociatedMessage_t;` (2认同)

Gre*_*osz 18

这是我自己的代码库中提取的静态断言的实现:Pre-C++11 Static Assertions Without Boost.

用法:

STATIC_ASSERT(expression, message);

当静态断言测试失败时,STATIC_ASSERTION_FAILED_AT_LINE_xxx_message会生成以某种方式包含的编译器错误消息.

message必须是一个有效的C++标识符,像no_you_cant_have_a_pony这样会产生一个编译器错误,包含:

STATIC_ASSERTION_FAILED_AT_LINE_1337_no_you_cant_have_a_pony :)

#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(true, ok);
STATIC_ASSERT(false, ko);

int main()
{
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 非常好!这是一个完整的解决方案(如果你想避免升压本身,那么这是一个很好的替代方案)+1 (2认同)