This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
Section: 23.4.1 [associative.general] Status: New Submitter: Tomasz Kaminski Opened: 2025-03-14 Last modified: 2025-08-29
Priority: 2
View all issues with New status.
Discussion:
The from_range deduction guide for maps currently do not handle ranges of tuple of two elements:
std::vector<int> v;
auto zv = std::views::zip(v, v);
std::map m4(std::from_range, zv); // Ill-formed, no-deduction guide
This seems to be result of merge conflict between P2165 (Compatibility between tuple, pair and tuple-like objects)
and P1206R4 (Conversions from ranges to containers): The helper range-key-type and
range-mapped-type aliases introduced by the later use the old formulation of ::first_type,
::second::type instead of tuple_element.
std::flat_map<int, float> fm; // iterator value_type is pair<int, float>
std::map m1(fm.begin(), fm.end()); // OK, deduces std::map<int, float>
auto tv = fm | std::views::transform(std::identity{}); // iterator value value_type is pair<int const&, float const&>
std::map m3(tv.begin(), tv.end()); // Ill-formed, deduces std::map<int const&, float&>
[2025-08-29; Reflector poll]
Set priority to 2 after reflector poll.
Proposed resolution:
This wording is relative to N5001.
[Drafting note: The proposed change also strips
constfrom the value type of themap, changing the behavior of previously working code:]std::pair<int const, float const> tp[2]; std::map m(std::begin(tp), std::end(tp)); // Was std::map<int, float const>, now std::map<int, float>
Modify 23.4.1 [associative.general] as indicated:
template<class InputIterator>
using iter-value-type =
typename iterator_traits<InputIterator>::value_type; // exposition only
template<class InputIterator>
using iter-key-type = remove_const_tremove_cvref_t<
tuple_element_t<0, iter-value-type<InputIterator>>>; // exposition only
template<class InputIterator>
using iter-mapped-type = remove_cvref_t<
tuple_element_t<1, iter-value-type<InputIterator>>>; // exposition only
template<class InputIterator>
using iter-to-alloc-type = pair<
add_const_t<
tuple_element_t<0, iter-value-type<InputIterator>>
iter-key-type<InputIterator>
>,
tuple_element_t<1, iter-value-type<InputIterator>>
iter-mapped-type<InputIterator>
>; // exposition only
template<ranges::input_range Range>
using range-key-type =
remove_const_t<typename ranges::range_value_t<Range>::first_type>
remove_cvref_t<tuple_element_t<0, ranges::range_value_t<Range>>>; // exposition only
template<ranges::input_range Range>
using range-mapped-type =
typename ranges::range_value_t<Range>::second_type
remove_cvref_t<tuple_element_t<1, ranges::range_value_t<Range>>>; // exposition only
template<ranges::input_range Range>
using range-to-alloc-type =
pair<add_const_t<
typename ranges::range_value_t<Range>::first_type
range-key-type<Range>
>,
typename ranges::range_value_t<Range>::second_type
range-mapped-type<Range>
>; // exposition only