Boost logo

Boost :

From: Michael Stevens (michael_at_[hidden])
Date: 2002-10-17 04:25:08

Thanks to David and Craig for the feedback,

>> template <class IntType>
>> class fred
>> {
>> static const bool x = std::numeric_limits<IntType>::is_integer;
>> BOOST_STATIC_ASSERT(std::numeric_limits<int>::is_integer); // OK
>> BOOST_STATIC_ASSERT(std::numeric_limits<IntType>::is_integer); // FAILS on definition of template!
>> };

> BOOST_STATIC_CONSTANT(bool, x = std::numeric_limits<IntType>::is_integer);

> You could also try forcing x to be an enum, if BOOST_STATIC_CONSTANT
> isn't already configured that way for vc7.

The suggestions led me to locate MSVC's problem with these templated assertions. It is having difficulty with the typedef mechanism used as part of the BOOST_STATIC_ASSERT. To try to come to a resolution I have looked into alternatives in boost/static_assert.hpp
I think it is important to fix at this point, as the problem is general, and will not be isolated to Random.

At present (for MSVC) STATIC_ASSERT uses the typedef mechanism. This fails with template paramter compile time constant. However the alternative enum mechanism DOES work. Iterestingly at present the enum mechanism is explictly not used for MSVC. This is due to a quoted problem with __LINE__ and /Zi. VC7 (not VC6) supplies the rather useful __COUNTER__ alternative, which does work. With this in mind I propose the following patch:

RCS file: /cvsroot/boost/boost/boost/static_assert.hpp,v
retrieving revision 1.9
diff -r1.9 static_assert.hpp
< #ifdef __BORLANDC__
< //
< // workaround for buggy integral-constant expression support:
< #endif

> #if !defined(__BORLANDC__) && !defined(__MWERKS__) && !defined(BOOST_MSVC)
< #if defined(BOOST_MSVC)
< // __LINE__ macro broken when -ZI is used see Q199057
< // fortunately MSVC ignores duplicate typedef's.
< #define BOOST_STATIC_ASSERT( B ) \
<    typedef ::boost::static_assert_test<\
<       sizeof(::boost::STATIC_ASSERTION_FAILURE< (bool)( B ) >)\
<       > boost_static_assert_typedef_
< #elif defined(BOOST_INTEL_CXX_VERSION)
< # define BOOST_STATIC_ASSERT( B ) \
> #define BOOST_STATIC_ASSERT( B ) \
< // generic version
> // generic typedef version
> #if defined(BOOST_MSVC)
> #if BOOST_MSVC >= 1300
> // MSVC7 Use __COUNTER__ as __LINE__ macro broken with /ZI (see Q199057)
> #define BOOST_STATIC_ASSERT( B ) \
>    enum { BOOST_JOIN(boost_static_assert_enum_, __COUNTER__) \
>       = sizeof(::boost::STATIC_ASSERTION_FAILURE< (bool)( B ) >) }
> #else
> // MSVC6 no generic solution
> #endif
> #else
> // generic enum version
> #endif
The patch removes the the current MSVC typedef implementation.
With the enum implementations, two alternatives for MSVC are added. The VC7 enum implementation is identical except it uses the __COUNTER__ macro which is preferable to __LINE__ anyway. The VC6 implementation is empty. I have no generic working alternative!
To avoid confusion I simplify the conditional compilation path so a single (line 60) #if is used to choose either enum or typedef implementations. The undocumented and unused macro BOOST_BUGGY_INTEGRAL_CONSTANT_EXPRESSIONS is removed.
This is a critical library for Boost. The changes only use new code for MSVC compilations. Regression testing shows no new problems for the enum version combined with __COUNTER__. Hopefully someone is willing to commit this to CVS. These broken compilers are rather annoying!
All the Best,

Boost list run by bdawes at, gregod at, cpdaniel at, john at