Boost logo

Boost :

From: Aleksey Gurtovoy (agurtovoy_at_[hidden])
Date: 2002-12-30 07:54:09


Jaap Suter wrote:
> what's the current status on using MPL on different
> compilers? I have looked
> at http://www.mywikinet.com/mpl/log.html but it seems not all
> meta-functions are listed there.

I would say that currently the tests cover about 80% of library
functionality, so the aforementioned page gives a pretty accurate answer to
your question, for Windows platform. In short, the library works with all of
them.

That said, unfortunately it cannot shield a user from all the bugs in
unconforming compilers; when writing your own complex template code, you
still have to have a certain amount of knowledge about the particular
compiler's idiosyncrasies. In these cases the library at least gives you
some patterns/workarounds to follow.

>
> I'm currently porting a library from Intel to GCC, MSVC7.0
> and BorlandC-5.5 and running into some problems.

Borland is probably going to be the most troublesome, here. It's known for
giving a lot of headache when one is dealing with compile-time integral
constant expression. Be sure to check John Maddock's "Coding Guidelines for
Integral Constant Expressions"
(http://www.boost.org/more/int_const_guidelines.htm), as well as MPL's
techniques to work around some of these problems.

> GCC is doing relatively okay. I'm moving from Borland-5.5 to 6.x
> soon, so I probably won't even bother with that one. So that
> leaves MSVC 7.0. However, compiling even relatively simple
> templates, I get errors pointing in the MPL source-code
> (which is a problem with MSVC, not with the actual sourcecode of
> course).

You happened to hit one of the VC 7.0 newly-introduced bugs (MSVC 6.5 is OK
in this regard), please see below.

>
> Note, I'm not even instantiating anything yet, this is just
> the first-phase compilation of a template definition.

Yep, that's a typical symptom of the problem.

> For example, consider:
>
> /*!
> \brief Meta function, returns the number of bits equal to
> 1 in a given number.
> \param N Some number. Concept: boost::mpl::integral_c
> \retval ::type boost::mpl::integral_c< size_t, Number of
> bits equal
>
> to 1 in
> N >
> */
> template < typename N >
> struct num_bits_set
> {
> private:
>
> template < typename Number >
> struct recurse
> {
>
> private:
> BOOST_STATIC_CONSTANT( typename Number::value_type,
>
> shift_right_value =
> N::value >> 1 );
> BOOST_STATIC_CONSTANT( typename Number::value_type,
>
> last_bit_set_value =
> N::value & 1 );
> typedef mpl::integral_c< size_t, last_bit_set_value >
> next_value;
>
> public:
>
> typedef typename mpl::plus<
> next_value,
> typename num_bits_set<
> mpl::integral_c<
> typename Number::value_type,
> shift_right_value > >::type
> >::type type;
> };
>
> public:
> typedef typename mpl::apply_if<
> typename mpl::equal_to<
> N,
> mpl::integral_c<
> typename N::value_type,
> 0 >
> >::type,
> mpl::integral_c< size_t, 0 >,
> recurse< N >
> >::type type;
> };
>
> Compiling this on MSVC 7.0 gives me the following errors:

[skip the errors]

Basically, the source of the problem here is that 'num_bits_set' and its
nested 'recurse' template depend on each other recursively; that, of course,
is a perfectly well-formed C++, but such recursive dependence means, in
particular, that when parsing the 'recurse' template the compiler haven't
seen the full definition for the 'num_bits_set' itself yet, and sometimes
this interacts badly with MSVC's so-called "early template instantiation"
bug (you can search the list archive to find out more about that one).

After you know what you are dealing with, the fix is simple:

#include "boost/mpl/if.hpp"
#include "boost/mpl/aux_/msvc_never_true.hpp"
#include "boost/detail/workaround.hpp"

// ...

template < typename N >
struct num_bits_set
{
    private:

    template < typename Number >
    struct recurse
    {

    private:
        BOOST_STATIC_CONSTANT( typename Number::value_type,
                                                         shift_right_value =
N::value >> 1 );
        BOOST_STATIC_CONSTANT( typename Number::value_type,
                                                        last_bit_set_value =
N::value & 1 );
        typedef mpl::integral_c< std::size_t, last_bit_set_value >
next_value;

    public:
#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
        typedef typename mpl::if_<
              mpl::aux::msvc_never_true<N>
            , mpl::integral_c<int,0>
            , typename num_bits_set<
                    mpl::integral_c<
                        typename Number::value_type,
                        shift_right_value > >::type
>::type v;
#else
        typedef typename num_bits_set<
                    mpl::integral_c<
                        typename Number::value_type,
                        shift_right_value > >::type v;
#endif

        typedef typename mpl::plus<
                next_value,
                v
>::type type;
    };

    // ...

Note that you'll need the latest CVS library sources for that (I had to bump
up a few #ifdefs to 7.0).

On aside note, a more efficient way to compute the number of set bits would
be a compile-time equivalent of this:

    template< typename N >
    int bit_count( N number )
    {
        int result = 0;
        typedef typename remove_signess<N>::type unsigned_;
        for (unsigned_ n = static_cast<unsigned_>(number); n; ++result)
            n &= n - 1;
        return result;
    }

>
> Anyway, any hints for the above would be appreciated, but the actual
> question is: is it worth it spending a lot of time on an MSVC7 port,
> or is this an effort doomed to fail from the start?

It depends on how much code you have in your library and, correspondingly,
how much resources you are willing to spend on it, but in general I wouldn't
say it's doomed. For one, you can count on MPL. It does work, reliably, on
both MSVC 7.0 and MSVC 6.5 (we use it routinely on the latter platform here
at work).

> I suppose this is hard to answer without knowing the library details and
the
> target-audience,

Yes, the later is the main factor, IMO.

> but considering I'm doing some rather complicated MPL stuff it is
> going to be one hell of a ride.

Probably the opposite - the more of the stuff you are doing is done through
the MPL, the less portability problems you'll have.

> Mmm, perhaps I'm better of waiting for the PTS supporting
> MSVC update. If not, any strategies or advice for tackling
> common problems with MPL on MSVC?

Well, I can think of only one major point worth mentioning - if you use your
own metafunctions in MPL's lambda expressions, they will require some
additional tweaking - please see
http://aspn.activestate.com/ASPN/Mail/Message/1445222 for the details.

Besides this, there shouldn't be any problems.

Aleksey


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk