[cfe-dev] static_assert without C++11 and with a message?

Richard Smith richard at metafoo.co.uk
Tue Jun 19 19:45:38 PDT 2012


On Tue, Jun 19, 2012 at 3:38 PM, Howard Hinnant <hhinnant at apple.com> wrote:
> On Jun 19, 2012, at 6:30 PM, Richard Smith wrote:
>
>> On Tue, Jun 19, 2012 at 9:06 AM, Howard Hinnant <hhinnant at apple.com> wrote:
>>> On Jun 19, 2012, at 3:22 AM, Stephen Kelly wrote:
>>>
>>>>
>>>> Hi there,
>>>>
>>>> I was looking into libc++, and noticed the implementation of static_assert
>>>> for pre-c++11 compilers.
>>>>
>>>> Inside of the _LIBCPP_HAS_NO_STATIC_ASSERT ifdef, there is a typo (__t
>>>> should be __m I presume?),
>>>
>>> Nope.
>>>
>>>> but even when that is fixed, I can't see how the
>>>> static assert macro could work.
>>>>
>>>> It would expand to
>>>>
>>>> typedef __static_assert_check<unsigned> "some message";
>>>>
>>>> in both the true and false case. For the false case it fails to compile the
>>>> __static_assert_check<unsigned> already, but for the true case it also fails
>>>> to compile. How should that work?
>>>
>>> For me, preprocessing this in C++03 mode:
>>>
>>> #include <__config>
>>>
>>> int main()
>>> {
>>>    const int i = 0;
>>>    static_assert(i == 0, "");
>>> }
>>>
>>> Yields:
>>>
>>> typedef __char16_t char16_t;
>>> typedef __char32_t char32_t;
>>>
>>> namespace std {
>>>  inline namespace __1 {
>>>  }
>>> }
>>>
>>> template <bool> struct __static_assert_test;
>>> template <> struct __static_assert_test<true> {};
>>> template <unsigned> struct __static_assert_check {};
>>>
>>> int main()
>>> {
>>>    const int i = 0;
>>>    typedef __static_assert_check<sizeof(__static_assert_test<(i == 0)>)> __t6;
>>
>> This isn't quite right: the first argument to static_assert is
>> contextually converted to bool. So a more correct emulation would
>> produce:
>>
>>    typedef __static_assert_check<sizeof(__static_assert_test<bool(i ==
>> 0)>)> __t6;
>>
>> Testcase:
>>
>>  int n;
>>  static_assert(&n, "");
>
> Right.  But your fix doesn't seem to be working:
>
> test.cpp:4:2: error: non-type template argument of type 'bool' is not an integral constant expression
>  static_assert(&n, "");
>  ^~~~~~~~~~~~~~~~~~~~~
> /Applications/Xcode45-DP1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/__config:378:63: note: expanded from
>      macro 'static_assert'
>    typedef __static_assert_check<sizeof(__static_assert_test<(bool(__b))>)> \
>                                                              ^~~~~~~~~~~

Hah, of course, the constant expression rules are tighter in C++98 too
:) Depending on how much you want to emulate C++11 semantics, you
could either stick with what you have, or enable full folding with the
__builtin_constant_p(...) ? ...  : ... hack.




More information about the cfe-dev mailing list