[MP11] Loosing const-qualification on type result with GCC 4.8 only

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

On 19-04-26 01:05:12, Mateusz Loskot wrote:
(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. [...] 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?
For the archive completeness, in case anyone is looking for answer to similar question: As Peter confirmed on the Slack, MP11 originally supported GCC 4.9+ and 4.8 support is partial, not without issues. My use case above was hit but one of such issues, in GCC 4.8, as commented here: https://github.com/boostorg/mp11/blob/e5d6e0d0b991a99c71a2b8f5057d0f0a1a89e0... #if !BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 40900 ) // g++ 4.7, 4.8 have difficulties with preserving top-level const BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke_q<Q, void>, void const>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke_q<Q, int[]>, int const[]>)); #endif Since GCC 4.8 is dying, it's a good idea to stop using it where MP11 + C++11 is required. Best regards, -- Mateusz Loskot, http://mateusz.loskot.net Fingerprint=C081 EA1B 4AFB 7C19 38BA 9C88 928D 7C2A BB2A C1F2

Hi Mateusz, Peter, On Sat, Apr 27, 2019 at 10:32 PM Mateusz Loskot via Boost < boost@lists.boost.org> wrote:
On 19-04-26 01:05:12, Mateusz Loskot wrote:
(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
[...]
https://github.com/boostorg/mp11/blob/e5d6e0d0b991a99c71a2b8f5057d0f0a1a89e0...
#if <https://github.com/boostorg/mp11/blob/e5d6e0d0b991a99c71a2b8f5057d0f0a1a89e060/test/mp_quote_trait.cpp#L47-L54%23if> !BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 40900 ) // g++ 4.7, 4.8 have difficulties with preserving top-level const BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke_q<Q, void>, void const>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke_q<Q, int[]>, int const[]>)); #endif
Since GCC 4.8 is dying, it's a good idea to stop using it where MP11 + C++11 is required.
how about wrapping the const type in mp_identity as a workaround before doing transforms, and then unwrapping?

O 19-04-28 10:20:58, Hans Dembinski wrote:
On Sat, Apr 27, 2019 at 10:32 PM Mateusz Loskot via Boost <boost@lists.boost.org> wrote:
On 19-04-26 01:05:12, Mateusz Loskot wrote:
(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
[...]
https://github.com/boostorg/mp11/blob/e5d6e0d0b991a99c71a2b8f5057d0f0a1a89e0...
#if !BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 40900 ) // g++ 4.7, 4.8 have difficulties with preserving top-level const BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke_q<Q, void>, void const>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke_q<Q, int[]>, int const[]>)); #endif
Since GCC 4.8 is dying, it's a good idea to stop using it where MP11 + C++11 is required.
how about wrapping the const type in mp_identity as a workaround before doing transforms, and then unwrapping?
As we discussed on Slack, it may work. I'm just not able, resource-wise, to maintain support for GCC 4.8 or similarly ancient compiler in GIL. Anyone who wishes to use GIL with such the oldies is welcome to submit PR. Alternatively, older Boost versions are available. Best regards, -- Mateusz Loskot, http://mateusz.loskot.net Fingerprint=C081 EA1B 4AFB 7C19 38BA 9C88 928D 7C2A BB2A C1F2
participants (2)
-
Hans Dembinski
-
Mateusz Loskot