From: Jaap Suter (boost_at_[hidden])
Date: 2004-11-15 16:40:47


Hello,

can any compiler expert give me feedback on whether there should be a
noticable difference in compilation speed between the following two
meta-functions:

template<class N, class M, class Q, class P>
struct foo : mpl::plus
    <
        N,
        typename mpl::minus
        <
            M,
            typename mpl::divides
            <
                Q,
                P
>::type
>::type
>::type
{};

and

template<int N, int M, int P, int Q>
struct foo
{
    enum
    {
        value = N + (M - (Q/P))
    };

    typedef boost::mpl::int<value> type;
}

The second version saves me a lot of template instantiations and many
header inclusions, at the cost of losing some genericity.

On the other hand, if the calculation becomes complicated, I find myself
using many enums to hold intermediate values, resulting in code like the
following:

template<class T>
struct next_number_with_same_num_bits
{
    enum
    {
        lowest_bit_set = T::value & (-T::value),
        lowest_bit_set_index = count_leading_zeroes<T>::type::value,
        next_t = T::value + lowest_bit_set,
        next_lowest_set_bit = next_t & (-next_t),
        mask = next_lowest_set_bit - lowest_bit_set,
        result_t = next_t | (mask >> (lowest_bit_set_index + 1))
    };

    typedef boost::mpl::int_<result_t> type;
};

which leads MSVC to run out of so-called compiler-keys much
quicker than if I reduce the above to the completely unreadable:

template<class T>
struct next_number_with_same_num_bits
{
    enum
    {
        result_t = (T::value + (T::value & (-T::value))) | ((((T::value +
(T::value & (-T::value))) & (-T::value - (T::value & (-T::value)))) -
(T::value & (-T::value))) >> (count_leading_zeroes<T>::type::value + 1))
    };

    typedef boost::mpl::int_<result_t> type;
};

Does anybody have any thoughts or comments on this technique, and is anybody
else using tricks around MPL to make sure your compiler still handles
things?

Thanks,

Jaap Suter