Created on 2024-07-16.00:00:00 last changed 1 month ago
Proposed resolution:
This wording is relative to N4986.
Modify [range.utility.conv.general] as indicated:
-4- Let
container-appendable
be defined as follows:template<class Container, class Ref> constexpr bool container-appendable = // exposition only requires(Container& c, Ref&& ref) { requires (requires { c.emplace_back(std::forward<Ref>(ref)); } || requires { c.push_back(std::forward<Ref>(ref)); } ||requires { c.emplace(c.end(), std::forward<Ref>(ref)); } ||requires { c.insert(c.end(), std::forward<Ref>(ref)); }); };-5- Let
container-append
be defined as follows:template<class Container> constexpr auto container-append(Container& c) { // exposition only return [&c]<class Ref>(Ref&& ref) { if constexpr (requires { c.emplace_back(declval<Ref>()); }) c.emplace_back(std::forward<Ref>(ref)); else if constexpr (requires { c.push_back(declval<Ref>()); }) c.push_back(std::forward<Ref>(ref));else if constexpr (requires { c.emplace(c.end(), declval<Ref>()); }) c.emplace(c.end(), std::forward<Ref>(ref));else c.insert(c.end(), std::forward<Ref>(ref)); }; };
[ 2024-08-02; Reflector poll ]
Set priority to 2 after reflector poll. "Would like to preserve the ability to use `emplace`. Tim suggested trying `emplace_hint` first, then `emplace`." "I tried it, it gets very verbose, because we might also want to try `insert(*it)` instead of `insert(c.end(), *it)` if `emplace(*it)` is not valid for associative containers, because `c.end()` might not be a good hint." "It might be suboptimal, but it still works."
[ 2024-07-23; This was caused by LWG 4016. ]
When ranges::to
constructs an associative container, if there is no range version constructor
for C
and the input range is not common range, ranges::to
will dispatch to the
bullet [range.utility.conv.to] (2.1.4), which first default-constructs the container
and emplaces the element through c.emplace(c.end(), *it)
.
emplace()
on an associative container as it does
not expect an iterator as the first argument, and since map::emplace()
, for instance, is not
constrained, which turns out a hard error because we are trying to make a pair
with
{it, pair}
.
Given that libstdc++ currently does not implement the range constructor for associative containers, the following
illustrates the issue:
#include <ranges>
#include <set>
auto s = std::views::iota(0)
| std::views::take(5)
| std::ranges::to<std::set>(); // hard error
The proposed resolution simply removes the emplace()
branch. Although this means that we always use
insert()
to fill associative containers, such an impact seems negligible.
History | |||
---|---|---|---|
Date | User | Action | Args |
2024-08-02 21:52:03 | admin | set | messages: + msg14294 |
2024-07-23 10:01:12 | admin | set | messages: + msg14261 |
2024-07-21 09:28:11 | admin | set | messages: + msg14258 |
2024-07-16 00:00:00 | admin | create |