C++11
和decltype
:_
#define UTILITY_PP_STRINGIZE_(x) #x
#define UTILITY_PP_STRINGIZE(x) UTILITY_PP_STRINGIZE_(x)
#define STATIC_ASSERT_TRUE(exp, msg) static_assert(::utility::StaticAssertTrue<decltype(exp), (exp)>::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg)
#define STATIC_ASSERT_TRUE1(exp, v1, msg) \
static_assert(::utility::StaticAssertTrue<decltype(exp), (exp), \
::utility::StaticAssertParam<decltype(v1), (v1)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg)
#define STATIC_ASSERT_TRUE2(exp, v1, v2, msg) \
static_assert(::utility::StaticAssertTrue<decltype(exp), (exp), \
::utility::StaticAssertParam<decltype(v1), (v1)>, \
::utility::StaticAssertParam<decltype(v2), (v2)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg)
#define STATIC_ASSERT_TRUE3(exp, v1, v2, v3, msg) \
static_assert(::utility::StaticAssertTrue<decltype(exp), (exp), \
::utility::StaticAssertParam<decltype(v1), (v1)>, \
::utility::StaticAssertParam<decltype(v2), (v2)>, \
::utility::StaticAssertParam<decltype(v3), (v3)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg)
#define STATIC_ASSERT_TRUE4(exp, v1, v2, v3, v4, msg) \
static_assert(::utility::StaticAssertTrue<decltype(exp), (exp), \
::utility::StaticAssertParam<decltype(v1), (v1)>, \
::utility::StaticAssertParam<decltype(v2), (v2)>, \
::utility::StaticAssertParam<decltype(v3), (v3)>, \
::utility::StaticAssertParam<decltype(v4), (v4)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg)
#define STATIC_ASSERT_FALSE(exp, msg) static_assert(::utility::StaticAssertFalse<decltype(exp), (exp)>::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg)
#define STATIC_ASSERT_FALSE1(exp, v1, msg) \
static_assert(::utility::StaticAssertFalse<decltype(exp), (exp), \
::utility::StaticAssertParam<decltype(v1), (v1)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg)
#define STATIC_ASSERT_FALSE2(exp, v1, v2, msg) \
static_assert(::utility::StaticAssertFalse<decltype(exp), (exp), \
::utility::StaticAssertParam<decltype(v1), (v1)>, \
::utility::StaticAssertParam<decltype(v2), (v2)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg)
#define STATIC_ASSERT_FALSE3(exp, v1, v2, v3, msg) \
static_assert(::utility::StaticAssertFalse<decltype(exp), (exp), \
::utility::StaticAssertParam<decltype(v1), (v1)>, \
::utility::StaticAssertParam<decltype(v2), (v2)>, \
::utility::StaticAssertParam<decltype(v3), (v3)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg)
#define STATIC_ASSERT_FALSE4(exp, v1, v2, v3, v4, msg) \
static_assert(::utility::StaticAssertFalse<decltype(exp), (exp), \
::utility::StaticAssertParam<decltype(v1), (v1)>, \
::utility::StaticAssertParam<decltype(v2), (v2)>, \
::utility::StaticAssertParam<decltype(v3), (v3)>, \
::utility::StaticAssertParam<decltype(v4), (v4)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg)
#define STATIC_ASSERT_EQ(v1, v2, msg) static_assert(::utility::StaticAssertEQ<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " == " UTILITY_PP_STRINGIZE(v2) "\": " msg)
#define STATIC_ASSERT_NE(v1, v2, msg) static_assert(::utility::StaticAssertNE<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " != " UTILITY_PP_STRINGIZE(v2) "\": " msg)
#define STATIC_ASSERT_LE(v1, v2, msg) static_assert(::utility::StaticAssertLE<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " <= " UTILITY_PP_STRINGIZE(v2) "\": " msg)
#define STATIC_ASSERT_LT(v1, v2, msg) static_assert(::utility::StaticAssertLT<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " < " UTILITY_PP_STRINGIZE(v2) "\": " msg)
#define STATIC_ASSERT_GE(v1, v2, msg) static_assert(::utility::StaticAssertGE<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " >= " UTILITY_PP_STRINGIZE(v2) "\": " msg)
#define STATIC_ASSERT_GT(v1, v2, msg) static_assert(::utility::StaticAssertGT<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " > " UTILITY_PP_STRINGIZE(v2) "\": " msg)
namespace utility
{
template <typename T, T v>
struct StaticAssertParam
{
};
template <typename T, T v, typename ...Params>
struct StaticAssertTrue;
template <typename T, T v>
struct StaticAssertTrue<T, v>
{
static const bool value = (v ? true : false);
};
template <typename T, T v, typename ...Params>
struct StaticAssertTrue
{
static const bool value = (v ? true : false);
static_assert(v ? true : false, "StaticAssertTrue with parameters failed.");
};
template <typename T, T v, typename ...Params>
struct StaticAssertFalse;
template <typename T, T v>
struct StaticAssertFalse<T, v>
{
static const bool value = (v ? false : true);
};
template <typename T, T v, typename ...Params>
struct StaticAssertFalse
{
static const bool value = (v ? false : true);
static_assert(v ? false : true, "StaticAssertFalse with parameters failed.");
};
template <typename U, typename V, U u, V v>
struct StaticAssertEQ
{
static const bool value = (u == v);
static_assert(u == v, "StaticAssertEQ failed.");
};
template <typename U, typename V, U u, V v>
struct StaticAssertNE
{
static const bool value = (u != v);
static_assert(u != v, "StaticAssertNE failed.");
};
template <typename U, typename V, U u, V v>
struct StaticAssertLE
{
static const bool value = (u <= v);
static_assert(u <= v, "StaticAssertLE failed.");
};
template <typename U, typename V, U u, V v>
struct StaticAssertLT
{
static const bool value = (u < v);
static_assert(u < v, "StaticAssertLT failed.");
};
template <typename U, typename V, U u, V v>
struct StaticAssertGE
{
static const bool value = (u >= v);
static_assert(u >= v, "StaticAssertGE failed.");
};
template <typename U, typename V, U u, V v>
struct StaticAssertGT
{
static const bool value = (u > v);
static_assert(u > v, "StaticAssertGT failed.");
};
}
用法:
struct A
{
int a[4];
};
#define Float1 1.1f
#define Float2 1.2f
int main()
{
static const int a = 3;
static const long b = 5;
static const long c = 7;
static const long d = 9;
STATIC_ASSERT_TRUE4(a == b && c == d, a, b, c, d, "long_expression_with_multiple_integral_variables");
#pragma message("----------------------------------------")
STATIC_ASSERT_TRUE(Float1 == Float2, "expression_with_floats");
#pragma message("----------------------------------------")
STATIC_ASSERT_EQ(10, sizeof(A), "simple_integral_expression_1");
#pragma message("----------------------------------------")
STATIC_ASSERT_EQ(11, sizeof(A), "simple_integral_expression_2");
return 0;
}
MSVC2017:
source_file.cpp(72): error C2338: StaticAssertTrue with parameters failed.
source_file.cpp(148): note: see reference to class template instantiation 'utility::StaticAssertTrue<bool,false,utility::StaticAssertParam<const int,3>,utility::StaticAssertParam<const long,5>,utility::StaticAssertParam<const long,7>,utility::StaticAssertParam<const long,9>>' being compiled
source_file.cpp(148): error C2338: expression: "a == b && c == d": long_expression_with_multiple_integral_variables
----------------------------------------
source_file.cpp(152): error C2338: expression: "1.1f == 1.2f": expression_with_floats
----------------------------------------
source_file.cpp(95): error C2338: StaticAssertEQ failed.
source_file.cpp(156): note: see reference to class template instantiation 'utility::StaticAssertEQ<int,size_t,10,16>' being compiled
source_file.cpp(156): error C2338: expression: "10 == sizeof(A)": simple_integral_expression_1
----------------------------------------
source_file.cpp(160): error C2338: expression: "11 == sizeof(A)": simple_integral_expression_2
GCC 4.8.x:
<source>: In instantiation of 'struct utility::StaticAssertTrue<bool, false, utility::StaticAssertParam<const int, 3>, utility::StaticAssertParam<const long int, 5l>, utility::StaticAssertParam<const long int, 7l>, utility::StaticAssertParam<const long int, 9l> >':
<source>:148:5: required from here
<source>:72:9: error: static assertion failed: StaticAssertTrue with parameters failed.
static_assert(v ? true : false, "StaticAssertTrue with parameters failed.");
^
<source>: In function 'int main()':
<source>:18:5: error: static assertion failed: expression: "a == b && c == d": long_expression_with_multiple_integral_variables
static_assert(::utility::StaticAssertTrue<decltype(exp), (exp), \
^
<source>:148:5: note: in expansion of macro 'STATIC_ASSERT_TRUE4'
STATIC_ASSERT_TRUE4(a == b && c == d, a, b, c, d, "long_expression_with_multiple_integral_variables");
^
<source>:150:63: note: #pragma message: ----------------------------------------
#pragma message("----------------------------------------")
^
<source>:4:41: error: static assertion failed: expression: "1.1f == 1.2f": expression_with_floats
#define STATIC_ASSERT_TRUE(exp, msg) static_assert(::utility::StaticAssertTrue<decltype(exp), (exp)>::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg)
^
<source>:152:5: note: in expansion of macro 'STATIC_ASSERT_TRUE'
STATIC_ASSERT_TRUE(Float1 == Float2, "expression_with_floats");
^
<source>:154:63: note: #pragma message: ----------------------------------------
#pragma message("----------------------------------------")
^
<source>: In instantiation of 'struct utility::StaticAssertEQ<int, long unsigned int, 10, 16ul>':
<source>:156:5: required from here
<source>:95:9: error: static assertion failed: StaticAssertEQ failed.
static_assert(u == v, "StaticAssertEQ failed.");
^
<source>:44:41: error: static assertion failed: expression: "10 == sizeof(A)": simple_integral_expression_1
#define STATIC_ASSERT_EQ(v1, v2, msg) static_assert(::utility::StaticAssertEQ<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " == " UTILITY_PP_STRINGIZE(v2) "\": " msg)
^
<source>:156:5: note: in expansion of macro 'STATIC_ASSERT_EQ'
STATIC_ASSERT_EQ(10, sizeof(A), "simple_integral_expression_1");
^
<source>:158:63: note: #pragma message: ----------------------------------------
#pragma message("----------------------------------------")
^
<source>: In instantiation of 'struct utility::StaticAssertEQ<int, long unsigned int, 11, 16ul>':
<source>:160:5: required from here
<source>:95:9: error: static assertion failed: StaticAssertEQ failed.
static_assert(u == v, "StaticAssertEQ failed.");
^
<source>:44:41: error: static assertion failed: expression: "11 == sizeof(A)": simple_integral_expression_2
#define STATIC_ASSERT_EQ(v1, v2, msg) static_assert(::utility::StaticAssertEQ<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " == " UTILITY_PP_STRINGIZE(v2) "\": " msg)
^
<source>:160:5: note: in expansion of macro 'STATIC_ASSERT_EQ'
STATIC_ASSERT_EQ(11, sizeof(A), "simple_integral_expression_2");
^