|
1 | 1 | #pragma once |
2 | 2 |
|
3 | 3 | // IWYU pragma: always_keep |
| 4 | +#include "morpheus/core/base/compiler.hpp" |
4 | 5 | #include "morpheus/core/conformance/ranges.hpp" |
5 | 6 | #include "morpheus/core/meta/concepts/string.hpp" |
6 | 7 | #include "morpheus/core/serialisation/concepts/read_serialisable.hpp" |
@@ -35,6 +36,24 @@ void serialise(Serialiser& serialiser, IsRange auto const& range) |
35 | 36 | serialiser.writer().endSequence(); |
36 | 37 | } |
37 | 38 |
|
| 39 | +template <typename T> |
| 40 | +concept IsAssociativeLike = requires { |
| 41 | + typename T::value_type; |
| 42 | + typename T::key_type; |
| 43 | +}; |
| 44 | + |
| 45 | +// template <typename T> |
| 46 | +// struct RangeDeserialiseValue |
| 47 | +//{ |
| 48 | +// using type = conf::ranges::range_value_t<T>; |
| 49 | +// }; |
| 50 | +// |
| 51 | +// template <IsMapLike T> |
| 52 | +// struct RangeDeserialiseValue<T> |
| 53 | +//{ |
| 54 | +// using type = std::pair<typename T::key_type, typename T::mapped_type>; |
| 55 | +// }; |
| 56 | + |
38 | 57 | template <concepts::ReadSerialiser Serialiser, IsRange T> |
39 | 58 | void deserialise(Serialiser& serialiser, T& range) |
40 | 59 | { |
@@ -69,14 +88,25 @@ void deserialise(Serialiser& serialiser, T& range) |
69 | 88 | template <concepts::ReadSerialiser Serialiser, IsRange T> |
70 | 89 | T deserialise(Serialiser& serialiser, std::type_identity<T>) |
71 | 90 | { |
72 | | -#if defined(__cpp_lib_ranges_to_container) && __cpp_lib_ranges_to_container >= 202202L |
73 | 91 | using ValueType = conf::ranges::range_value_t<T>; |
74 | | - auto seq = serialiser.template sequence<ValueType>(); |
75 | | - return conf::ranges::to<T>(std::move(seq)); |
| 92 | + |
| 93 | +#if defined(__cpp_lib_ranges_to_container) && __cpp_lib_ranges_to_container >= 202202L |
| 94 | + static constexpr bool isGcc14 = (MORPHEUS_COMPILER == MORPHEUS_GNUC_COMPILER) && (MORPHEUS_COMP_VER >= 140000000) && (MORPHEUS_COMP_VER < 150000000); |
| 95 | + |
| 96 | + if constexpr (isGcc14 && IsAssociativeLike<T>) |
| 97 | + { |
| 98 | + // We must work around Gcc's std::ranges::to implementation for associative containers: |
| 99 | + // https://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#4121 |
| 100 | + T range; |
| 101 | + serialiser.deserialise(range); |
| 102 | + return range; |
| 103 | + } |
| 104 | + else |
| 105 | + { |
| 106 | + return conf::ranges::to<T>(serialiser.template sequence<ValueType>()); |
| 107 | + } |
76 | 108 | #elif defined(__cpp_lib_containers_ranges) && __cpp_lib_containers_ranges >= 202202L |
77 | | - using ValueType = conf::ranges::range_value_t<T>; |
78 | | - auto seq = serialiser.template sequence<ValueType>(); |
79 | | - return T(std::from_range, std::move(seq)); |
| 109 | + return T(std::from_range, serialiser.template sequence<ValueType>()); |
80 | 110 | #else |
81 | 111 | T range; |
82 | 112 | serialiser.deserialise(range); |
|
0 commit comments