|
Boost : |
From: Greg Chicares (chicares_at_[hidden])
Date: 2001-05-24 22:49:04
Beman Dawes wrote:
>
> This program works as expected with the GNU, Metrowerks, and Microsoft
> compilers:
>
> #include <iostream>
> #include <boost/static_assert.hpp>
>
> template< typename T >
> void f( T & t )
> {
> std::cout << sizeof(T) << "\n";
> BOOST_STATIC_ASSERT( sizeof(T) ); // line in question
> }
>
> int main()
> {
> long l;
> f(l);
> return 0;
> }
>
> With the Borland 5.5.1 and Intel 5.0 compilers, the BOOST_STATIC_ASSERT
> fails:
>
> Borland:
> Error E2450 c:/boost/site/libs/smart_ptr/test.cpp 8: Undefined structure
> 'boost:
> :STATIC_ASSERTION_FAILURE<4>' in function f<long>(long &)
> Error E2109 c:/boost/site/libs/smart_ptr/test.cpp 8: Not an allowed type in
> func
> tion f<long>(long &)
>
> Intel:
> c:/boost/site/libs/smart_ptr/test.cpp(8) : error #70: incomplete type is
> not allowed
> BOOST_STATIC_ASSERT( sizeof(T) );
> ^
> detected during instantiation of "void f(T &) [with T=long]"
I don't know about intel, but it looks like borland doesn't convert
an integral-type value that's neither 0 nor 1 to bool(true) here
template <bool> struct STATIC_ASSERTION_FAILURE;
while gcc does.
Simplified example:
BOOST_STATIC_ASSERT( 1 ); // OK
BOOST_STATIC_ASSERT( 4 ); // asserts (with borland)
If the purpose of the macro is only to verify that something which
is notionally bool is not false, then is there any harm in saying
that a bit more explicitly?
- BOOST_STATIC_ASSERT( sizeof(T) ); // line in question
+ BOOST_STATIC_ASSERT( !!sizeof(T) );
This works with borland 5.5.1 . I don't like '!!' in general
because it masks problems with uninitialized bools, but the
domain of BOOST_STATIC_ASSERT is integral-constant-expressions,
so it seems OK here.
Assuming it's desired that
BOOST_STATIC_ASSERT( 4 );
not assert (for compatibility with the standard assert macro),
would this be an appropriate change to static_assert.hpp?
// alternative enum based implementation:
#define BOOST_STATIC_ASSERT( B ) \
enum { BOOST_ASSERT_JOIN(boost_static_assert_enum_, __LINE__) \
- = sizeof(::boost::STATIC_ASSERTION_FAILURE< ( B ) >) }
+ = sizeof(::boost::STATIC_ASSERTION_FAILURE< ( !!B ) >) }
#endif
(At least at the present time, the alternative enum implementation
is used only for borland; maybe something similar should be done
for intel too?)
/boost/boost_1_21_2/libs/static_assert/static_assert.htm says:
The header <boost/static_assert.hpp> supplies a single macro
BOOST_STATIC_ASSERT(x), which generates a compile time error
message if the integral-constant-expression x is not true.
[^^^^^^^^^^^]
In other words it is the compile time equivalent of the
assert macro
Should 'is not true' be changed? E.g.
if the integral-constant-expression x, when converted to bool,
is not true. ^^^^^^^^^^^^^^^^^^^^^^^^^
> Are these compilers wrong, or is there a problem with BOOST_STATIC_ASSERT?
>
> (Both produce the expected output if the line in question is commented
> out.)
I think it's equivalent to this simplified test case:
template <bool> struct X;
template <> struct X<true>{};
int main()
{
sizeof( X<4> ); // gcc: OK; borland: not OK
}
Isn't it an error not to accept the conversion 4 --> true [conv.bool]?
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk