26

私が働いている会社ではブーストが禁止されているので、その機能を純粋なC++で実装する必要があります。私はブーストソースを調べましたが、少なくとも私にとっては、それらは複雑すぎて理解できないようです。C ++ 0x標準で呼ばれるものがあることは知っていstatic_assert()ますが、C++0xの機能は使用したくありません。

4

6 に答える 6

27

もう 1 つのトリック (C で使用できます) は、アサートが失敗した場合に負のサイズで配列を構築しようとすることです。

#define ASSERT(cond) int foo[(cond) ? 1 : -1]

おまけとして、オブジェクトの代わりに typedef を使用できます。これにより、より多くのコンテキストで使用でき、成功したときに発生しなくなります。

#define ASSERT(cond) typedef int foo[(cond) ? 1 : -1]

最後に、名前が衝突する可能性が少ない (そして少なくとも別の行で再利用可能な) 名前を作成します。

#define CAT_(a, b) a ## b
#define CAT(a, b) CAT_(a, b)
#define ASSERT(cond) typedef int CAT(AsSeRt, __LINE__)[(cond) ? 1 : -1]
于 2009-12-30T12:52:48.313 に答える
21
template<bool> struct StaticAssert;
template<> struct StaticAssert<true> {};

int main() {
   StaticAssert< (4>3) >(); //OK
   StaticAssert< (2+2==5) >(); //ERROR
}
于 2009-12-30T12:45:08.497 に答える
18

私のコードベースから抽出した静的アサーションの私自身の実装は次のとおりPre-C++11 Static Assertions Without Boostです。

使用法:

STATIC_ASSERT(expression, message);

静的アサーション テストが失敗すると、なんらかの内容を含むコンパイラ エラー メッセージSTATIC_ASSERTION_FAILED_AT_LINE_xxx_messageが生成されます。

messageno_you_cant_have_a_pony次のようなコンパイラ エラーが生成されるように、有効な C++ 識別子である必要があります。

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;
}
于 2009-12-30T13:17:01.877 に答える
4

Boost ソース ファイルから独自のコードにマクロをコピーするだけです。Boost がサポートするすべてのコンパイラをサポートする必要がない場合は、コンパイラに適した定義を選択し#ifdef、そのファイルの残りの s を省略できます。

于 2009-12-30T12:51:50.010 に答える
4

私はこれがうまくいくと信じています:

template<bool> struct CompileTimeAssert;   
template<> struct CompileTimeAssert<true>{};
#define STATIC_ASSERT(e) (CompileTimeAssert <(e) != 0>())
于 2010-10-30T02:55:45.873 に答える
2

私は次のヘッダーファイルを使用していますが、コードは他の誰かからリッピングされています...

#ifndef STATIC_ASSERT__H
#define STATIC_ASSERT__H

/* ripped from http://www.pixelbeat.org/programming/gcc/static_assert.html */

#define ASSERT_CONCAT_(a, b) a##b
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
/* These can't be used after statements in c89. */
#ifdef __COUNTER__
  /* microsoft */
  #define STATIC_ASSERT(e) enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) }
#else
  /* This can't be used twice on the same line so ensure if using in headers
   * that the headers are not included twice (by wrapping in #ifndef...#endif)
   * Note it doesn't cause an issue when used on same line of separate modules
   * compiled with gcc -combine -fwhole-program.  */
  #define STATIC_ASSERT(e) enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }
#endif

/* http://msdn.microsoft.com/en-us/library/ms679289(VS.85).aspx */
#ifndef C_ASSERT
#define C_ASSERT(e) STATIC_ASSERT(e)
#endif

#endif
于 2009-12-30T13:13:41.790 に答える