Browse Source

When using C++11, use static_assert to implement COMPILE_ASSERT.

This is a cherry-pick from the Chromium project, from where this
implementation of basictypes.h once originated:

https://chromium.googlesource.com/chromium/src/+/539fc83
pull/742/head
Fredrik Roubert 11 years ago
parent
commit
768e05f0bc
2 changed files with 82 additions and 9 deletions
  1. +60
    -5
      cpp/src/phonenumbers/base/basictypes.h
  2. +22
    -4
      tools/cpp/src/base/basictypes.h

+ 60
- 5
cpp/src/phonenumbers/base/basictypes.h View File

@ -189,17 +189,72 @@ char (&ArraySizeHelper(const T (&array)[N]))[N];
// the expression is false, most compilers will issue a warning/error
// containing the name of the variable.
#if __cplusplus >= 201103L
// Under C++11, just use static_assert.
#define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
#else
template <bool>
struct CompileAssert {
};
#if !defined(COMPILE_ASSERT)
#if __cplusplus >= 201103L
#define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
// Annotate a variable indicating it's ok if the variable is not used.
// (Typically used to silence a compiler warning when the assignment
// is important for some other reason.)
// Use like:
// int x ALLOW_UNUSED = ...;
#if defined(COMPILER_GCC)
#define ALLOW_UNUSED __attribute__((unused))
#else
#define COMPILE_ASSERT(expr, msg) \
typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
#define ALLOW_UNUSED
#endif
#define COMPILE_ASSERT(expr, msg) \
typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] ALLOW_UNUSED
// Implementation details of COMPILE_ASSERT:
//
// - COMPILE_ASSERT works by defining an array type that has -1
// elements (and thus is invalid) when the expression is false.
//
// - The simpler definition
//
// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
//
// does not work, as gcc supports variable-length arrays whose sizes
// are determined at run-time (this is gcc's extension and not part
// of the C++ standard). As a result, gcc fails to reject the
// following code with the simple definition:
//
// int foo;
// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
// // not a compile-time constant.
//
// - By using the type CompileAssert<(bool(expr))>, we ensures that
// expr is a compile-time constant. (Template arguments must be
// determined at compile-time.)
//
// - The outer parentheses in CompileAssert<(bool(expr))> are necessary
// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
//
// CompileAssert<bool(expr)>
//
// instead, these compilers will refuse to compile
//
// COMPILE_ASSERT(5 > 0, some_message);
//
// (They seem to think the ">" in "5 > 0" marks the end of the
// template argument list.)
//
// - The array size is (bool(expr) ? 1 : -1), instead of simply
//
// ((expr) ? 1 : -1).
//
// This is to avoid running into a bug in MS VC 7.1, which
// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
#endif
} // namespace phonenumbers


+ 22
- 4
tools/cpp/src/base/basictypes.h View File

@ -230,15 +230,31 @@ inline To implicit_cast(From const &f) {
// the expression is false, most compilers will issue a warning/error
// containing the name of the variable.
#if __cplusplus >= 201103L
// Under C++11, just use static_assert.
#define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
#else
template <bool>
struct CompileAssert {
};
#if !defined(COMPILE_ASSERT)
#define COMPILE_ASSERT(expr, msg) \
typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
// Annotate a variable indicating it's ok if the variable is not used.
// (Typically used to silence a compiler warning when the assignment
// is important for some other reason.)
// Use like:
// int x ALLOW_UNUSED = ...;
#if defined(COMPILER_GCC)
#define ALLOW_UNUSED __attribute__((unused))
#else
#define ALLOW_UNUSED
#endif
#define COMPILE_ASSERT(expr, msg) \
typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] ALLOW_UNUSED
// Implementation details of COMPILE_ASSERT:
//
// - COMPILE_ASSERT works by defining an array type that has -1
@ -261,7 +277,7 @@ struct CompileAssert {
// expr is a compile-time constant. (Template arguments must be
// determined at compile-time.)
//
// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
// - The outer parentheses in CompileAssert<(bool(expr))> are necessary
// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
//
// CompileAssert<bool(expr)>
@ -280,6 +296,8 @@ struct CompileAssert {
// This is to avoid running into a bug in MS VC 7.1, which
// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
#endif
// Used to explicitly mark the return value of a function as unused. If you are
// really sure you don't want to do anything with the return value of a function
// that has been marked WARN_UNUSED_RESULT, wrap it with this. Example:


Loading…
Cancel
Save