Boost logo

Boost :

Subject: [boost] [MP11] Loosing const-qualification on type result with GCC 4.8 only
From: Mateusz Loskot (mateusz_at_[hidden])
Date: 2019-04-25 23:05:12


Hi,

(initially posted to https://lists.boost.org/boost-users/2019/04/89778.php)

I prepared a lenghty MWE which reproduces my problem with
type manipulation using MP11 that for some reason looses
const-qualification on a ::type result

Here it is at https://godbolt.org/z/eCsakP and copied below.
I hope the XXXXXX comments make sense and important static
assertions in the main() at the bottom explain what
is the expected result.

```
#include <boost/mp11.hpp>
#include <cstdint>
#include <type_traits>
namespace mp11 = boost::mp11;

template <typename BitField, int FirstBit, int NumBits, bool IsMutable>
struct bit_range_reference { /* long definition, irrelevant */ };

template <typename BitField, typename FirstBit, typename NumBits>
struct bit_range_reference_type
{
    using type = bit_range_reference
    <
        BitField, FirstBit::value, NumBits::value, true
> const; // XXXXXX Why this const gets lost with GCC 4.8 XXXXXX
};

template <typename BitField, typename RangeBitSizes>
class bit_range_reference_list
{
    template <typename FirstBit, typename NumBits>
    using reference_type = typename bit_range_reference_type
    <
        BitField, FirstBit, NumBits
>::type; // XXXXXX Should carry the const, shouldn't? GCC >4.8 do.

    // If RangeBitSizes is mp11::mp_list_c<int,7,7,2>
    // then first_bit_list will be mp11::mp_list_c<int,0,7,14,16>
    using first_bit_list = mp11::mp_fold_q
        <
            RangeBitSizes,
            mp11::mp_list<std::integral_constant<int, 0>>,
            mp11::mp_bind
            <
                mp11::mp_push_back,
                mp11::_1,
                mp11::mp_bind
                <
                    mp11::mp_plus,
                    mp11::mp_bind<mp11::mp_back, mp11::_1>,
                    mp11::_2
>
>
>;
    static_assert(mp11::mp_at_c<first_bit_list, 0>::value == 0,
        "first bit must be 0");
public:
    using type = mp11::mp_transform
        <
            reference_type,
            mp11::mp_pop_back<first_bit_list>,
            RangeBitSizes
>;
};

using reference3_list = typename bit_range_reference_list
<
    std::uint8_t,
    mp11::mp_list_c<int, 3>
>::type;

int main()
{
    using r1_t = mp11::mp_at_c<reference3_list, 0>;
    using r2_t = bit_range_reference<std::uint8_t, 0, 3, true>;
    using r2c_t= bit_range_reference<std::uint8_t, 0, 3, true> const;

//#if defined(__GNUC__) && (__GNUC__ == 4)
    // GCC 4.8 compiles, later versions of GCC fail to compile
    static_assert(std::is_same<r1_t, r2_t>::value,
        "GCC says r1_t is const-qualified");
//#else
    // GCC 4.9, 5, 6, 7, 8 versions compile, GCC 4.8 fail to compile
    static_assert(std::is_same<r1_t, r2c_t>::value,
        "GCC says r1_t is NOT const-qualified");
//#endif
}
```

To summary, I expect this to yield true:

std::is_same
<
    mp11::mp_at_c<reference3_list, 0>
    bit_range_reference<std::uint8_t, 0, 3, true> const
>

I got this confirmed by all GCC versions but GCC 4.8.
(clang and MSVC also seem to agree with the GCC >= 4.9)

Is mp11::mp_transform loosing const-qualification
or have I made a mistake somewhere?

I'm using Boost.MP11 from Boost 1.70 and from current develop branch

Best regards,

-- 
Mateusz Loskot, http://mateusz.loskot.net

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