STD :: ranges ::是否允许转换为STD :: MAP?

发布于 2025-01-25 22:57:27 字数 564 浏览 2 评论 0原文

std :: ranges :: to paper wg21.link/p1206中,概述部分具有以下内容

//Supports converting associative container to sequence containers
auto f = ranges::to<vector>(m);

,但是我找不到转换为std :: map 在本文的其余部分中被载入。我尝试了range-v3和sy Brand的范围:: to in https:// https:// github.com/tartanllama/ranges ,它们都没有编译代码将范围转换为std :: map。那么,这只是这些库中缺少的还是正在转换为std :: Map不允许真正允许的?

In the std::ranges::to paper wg21.link/p1206 ths overview section has the following

//Supports converting associative container to sequence containers
auto f = ranges::to<vector>(m);

However I can't find where the detail of converting to a std::map is descibed in the rest of the paper. I tried range-v3 and Sy Brand's implementation of ranges::to in https://github.com/TartanLlama/ranges and neither of them compiles code converting a range to a std::map. So is this just missing from those libraries or is converting to a std::map not really intended to be allowed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

花期渐远 2025-02-01 22:57:27

std :: ranges :: to允许转换为std :: map

是的。

我尝试了range-v3和sy Brand的范围:: to in https: //github.com/tartanllama/ranges ,它们都没有编译代码将范围转换为std :: map

的打破:

#include <map>
#include <vector>
#include <range/v3/range/conversion.hpp>

int main() {
    std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}};

    // this works (explicit)
    // m1 is a std::map<int, int>
    auto m1 = ranges::to<std::map<int, int>>(v);

    // this works (deduced with a pipe)
    // m2 is a std::map<int, int>
    auto m2 = v | ranges::to<std::map>();

    // but this does not (deduced, direct call)
    auto m3 = ranges::to<std::map>(v);
}

问题是,由于某种原因,范围V3中的类模板直接调用版本特别尝试实例化c&lt; range_value_t&lt&lt&gt;&gt;&gt;(这将是std :: map&lt; std :: pair&lt; int,int&gt;&gt;在这种情况下,显然是错误的),即使这里已经有一个元功能可以做正确的事情,并且会推断出std :: map&lt; int,int&gt;(由管道版本使用)。

范围:: to在标准库中指定了这两个执行相同(正确)的事情,因此这将在C ++ 23中起作用。这只是范围V3中的一个简单错误修复。

Does std::ranges::to allow converting to a std::map?

Yes.

I tried range-v3 and Sy Brand's implementation of ranges::to in https://github.com/TartanLlama/ranges and neither of them compiles code converting a range to a std::map

I haven't tried Sy's implementation, and it looks like range-v3's implementation is weirdly broken:

#include <map>
#include <vector>
#include <range/v3/range/conversion.hpp>

int main() {
    std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}};

    // this works (explicit)
    // m1 is a std::map<int, int>
    auto m1 = ranges::to<std::map<int, int>>(v);

    // this works (deduced with a pipe)
    // m2 is a std::map<int, int>
    auto m2 = v | ranges::to<std::map>();

    // but this does not (deduced, direct call)
    auto m3 = ranges::to<std::map>(v);
}

The issue is that the class template direct call version in range-v3 for some reason specifically tries to instantiate C<range_value_t<R>> (which would be std::map<std::pair<int, int>> in this case, clearly wrong) even though there is a metafunction here already that does the right thing and would deduce std::map<int, int> (used by the pipe version).

The ranges::to in the standard library specifies these two to do the same (correct) thing, so this will work in C++23. This is just an easy bug fix in range-v3.

蓝礼 2025-02-01 22:57:27

所以这只是从这些库中缺少或正在转换为
std :: Map不太允许吗?

STD :: MAP to std :: vector:

根据 [range.utility.conv.to] ,这

map<int, double> m;
auto f = ranges::to<vector>(m);

将调用以下超载

 模板&lt; template&lt; class ...&gt; C类,Input_range R,类... Args&gt;
  constexpr auto to(r&amp;&amp; r,args&amp;&amp; ... args); 
 

deduce_expr 定义如下:

  • c(dectval&lt; r&gt;(),dectval&lt; args&gt;()...)如果这是有效的表达式,
  • 否则,c(from_range,dectval&lt; r&gt;(),dectval&lt; args&gt;()...)如果这是有效的表达式,
  • 否则,c(dectval&lt; input-eterator&gt;(),dectval&lt; input-itterator&gt;(),dectval&lt; args&gt;()...)如果这是有效的表达式,< /li>
  • 否则,该程序的形式不佳。

返回to&lt; decltype(deduce_expr)&gt;(std :: forthrow&lt&lt; r&gt;(r),std :: forward :: forward&lt; args&gt;(args)...)<(args)...)< /代码>。


其中cvectorr is map&lt; int,double&gt;&gt; and args。 ..是空参数包。请注意,C ++ 23介绍以下 range range版本构造函数 for <代码>向量

 模板&lt;容器兼容范围&lt; t&gt; R&GT;
  constexpr vector(from_range_t,r&amp;&amp; rg,const Arlocator&amp; = astocator());
 

效果:构造一个范围rg的向量对象,
使用指定的分配器。

以及以下ctad

template<ranges::input_­range R, class Allocator = allocator<ranges::range_value_t<R>>>
  vector(from_range_t, R&&, Allocator = Allocator())
    -> vector<ranges::range_value_t<R>, Allocator>;

so c(from_range,dectval&lt; r&gt;())是一个有效的表达式, deduce_expr 的类型将为<代码> vector&lt; pair&lt; const int,double&gt; ,它将进一步调用,

to<vector<pair<const int, double>>>(m);

该>将使用value_type of of Pair&const构建vector通过范围版本构造函数,int,double&gt;

因此,范围:: to&lt; vector&gt;(m)在C ++ 23中基本上等同于

map<int, double> m;
vector f(m.begin(), m.end());

range-v3失败是因为其内部实现检测vector&lt; pair&lt; const int,double double&gt;是可保留的,因此首先将默认默认构建vector vector和调用v.reserve()预先分配内存,然后通过调用map通过调用v.assign(),但由于Pair&lt; const int,double&gt;无法复制,因此编译失败。

我怀疑这是范围V3的实现错误,因为如果vector's 储备()函数,则它将编译,并且此优化超负荷似乎并不限制value_type必须

复制

auto g = ranges::to<map>(f);

可 /code>还具有 sustructors 和对应的catd in在C ++ 23中,

template<container-compatible-range<value_type> R>
  map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator());

因此遵循游戏的相同规则,我们将获得map&lt; int,double&gt;

So is this just missing from those libraries or is converting to a
std::map not really intended to be allowed?

std::map to std::vector:

According to the description of [range.utility.conv.to], this

map<int, double> m;
auto f = ranges::to<vector>(m);

will invoke the following overload

template<template<class...> class C, input_­range R, class... Args>
  constexpr auto to(R&& r, Args&&... args); 

Let DEDUCE_­EXPR be defined as follows:

  • C(declval<R>(), declval<Args>()...) if that is a valid expression,
  • otherwise, C(from_­range, declval<R>(), declval<Args>()...) if that is a valid expression,
  • otherwise, C(declval<input-iterator>(), declval<input-iterator>(), declval<Args>()...) if that is a valid expression,
  • otherwise, the program is ill-formed.

Returns: to<decltype(DEDUCE_­EXPR)>(std​::​forward<R>(r), std​::​forward<Args>(args)...).

Where C is vector, R is map<int, double>&, and Args... is empty parameter pack. Note that C++23 introduces the following range version constructor for vector

template<container-compatible-range<T> R>
  constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator());

Effects: Constructs a vector object with the elements of the range rg,
using the specified allocator.

and the following CTAD

template<ranges::input_­range R, class Allocator = allocator<ranges::range_value_t<R>>>
  vector(from_range_t, R&&, Allocator = Allocator())
    -> vector<ranges::range_value_t<R>, Allocator>;

So C(from_range, declval<R>()) is a valid expression, and the type of DEDUCE_EXPR will be vector<pair<const int, double>>, which will further invoke

to<vector<pair<const int, double>>>(m);

which will construct a vector with value_type of pair<const int, double> through the range version constructor.

So ranges::to<vector>(m) in C++23 is basically equivalent to

map<int, double> m;
vector f(m.begin(), m.end());

The reason range-v3 fails is that its internal implementation detects that vector<pair<const int, double>> is reservable, so it will first default construct the vector and call v.reserve() to pre-allocate the memory, and then copy the map by calling v.assign(), but since pair<const int, double> is not copy assignable, so compilation fails.

I suspect this is an implementation bug of range-v3, since it would compile if the vector's reserve() function didn't exist, and this optimized overload doesn't seem to constrain that the value_type must be copy-assignable.

std::vector to std::map:

And for the following

auto g = ranges::to<map>(f);

Since std::map also has the following constructors and corresponding CATD in in C++23

template<container-compatible-range<value_type> R>
  map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator());

So following the same rules of the game, we will get a map<int, double>.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文