WriteCompilerDetectionHeader generates broken static_assert macro for c++98
write_compiler_detection_header
generates for the cxx_static_assert
feature and the gcc compiler something like this:
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__))
# define FOO_COMPILER_CXX_STATIC_ASSERT 1
# else
# define FOO_COMPILER_CXX_STATIC_ASSERT 0
# endif
[...]
# if FOO_COMPILER_CXX_STATIC_ASSERT
# define FOO_STATIC_ASSERT(X) static_assert(X, #X)
# define FOO_STATIC_ASSERT_MSG(X, MSG) static_assert(X, MSG)
# else
template<bool> struct FOOStaticAssert;
template<> struct FOOStaticAssert<true>{};
# define FOO_STATIC_ASSERT(X) sizeof(FOOStaticAssert<X>)
# define FOO_STATIC_ASSERT_MSG(X, MSG) sizeof(FOOStaticAssert<X>)
# endif
This macros, that works everywhere in c++11 will not work everywhere in c++98. For example:
#include "foo.h"
template <int val>
struct data_structure
{
FOO_STATIC_ASSERT_MSG((val > 0), "val should be greater than 0");
};
int main()
{
#ifndef FAIL_ASSERT
data_structure<42> ds_ok;
#else
data_structure<-5> ds_not_ok;
#endif
}
In c++11:
$ g++ -std=c++11 -DFAIL_ASSERT=0 -o /tmp/a.out /tmp/foo.cpp # compiles as expected
$ g++ -std=c++11 -DFAIL_ASSERT=1 -o /tmp/a.out /tmp/foo.cpp # fails as expected
/tmp/foo.cpp: In instantiation of ‘struct data_structure<-5>’:
/tmp/foo.cpp:32:24: required from here
/tmp/foo.cpp:10:43: error: static assertion failed: val should be greater than 0
# define FOO_STATIC_ASSERT_MSG(X, MSG) static_assert(X, MSG)
^
/tmp/foo.cpp:23:5: note: in expansion of macro ‘FOO_STATIC_ASSERT_MSG’
FOO_STATIC_ASSERT_MSG((val > 0), "val should be greater than 0");
^
In c++98:
$ g++ -std=c++98 -DFAIL_ASSERT=0 -o /tmp/a.out /tmp/foo.cpp # fails!!
/tmp/foo.cpp:15:43: error: expected unqualified-id before ‘sizeof’
# define FOO_STATIC_ASSERT_MSG(X, MSG) sizeof(FOOStaticAssert<X>)
^
/tmp/foo.cpp:23:5: note: in expansion of macro ‘FOO_STATIC_ASSERT_MSG’
FOO_STATIC_ASSERT_MSG((val > 0), "val should be greater than 0");
^
I don't know if this behaviour is expected, or if I'm doing something wrong but I cannot find documentation about this anywhere. Since this macro generates code that is not portable, I'd rather have it defined empty in c++98.