std::string从(另一个字符串的)转换视图创建 a 的最简洁和/或惯用的方法是什么?
我能想到的最好的方法是std::ranges::copy将视图和插入器用作参数,即使这样也只被 gcc(10.2 和主干)接受,但不接受 clang 11.x。
对于大多数ranges算法,我认为目的是operator|可以在函数的第一个参数是范围时使用,所以我想知道为什么第二个和恕我直言的更清洁变体不能编译(错误消息是没有copy找到匹配) ,并且是最终编译它的意图,还是什么?
我尝试了 gcc 10.2 和 gcc (11) 主干。Clang 也不编译第一种形式:(
#include <algorithm>
#include <cctype>
#include <iterator>
#include <ranges>
#include <string>
int main() {
std::string original = "foo";
std::string upper;
// This compiles on gcc 10.2/11-trunk only
std::ranges::copy(
original
| std::ranges::views::transform([](char c){return std::toupper(c);}),
std::back_inserter(upper)
);
// The below doesn't compile period
original
| std::ranges::views::transform([](char c){return std::toupper(c);})
| std::ranges::copy(std::back_inserter(upper));
}
Run Code Online (Sandbox Code Playgroud)
对于大多数范围算法,我认为目的是
operator|只要函数的第一个参数是范围就可以使用
这不太对。operator|仅适用于第一个参数是一个范围并且结果是一个范围的那些算法。
transform、filter、take等都是取一个范围并返回一个范围的算法。更具体地说,他们采用 aviewable_range并返回 a view。
但是对于不返回范围的所有其他算法 - max、find_if、any_of等 - 没有|其他选择。所以这:
original
| std::ranges::views::transform([](char c){return std::toupper(c);})
| std::ranges::copy(std::back_inserter(upper));
Run Code Online (Sandbox Code Playgroud)
甚至不打算工作,因为copy不是返回 a 的算法之一view,所以它没有得到|支持。管道重写运算符提案 ( P2011 )的动机之一是能够使用此类功能(无需大量库机制使其工作所需)。
另一方面,这:
std::ranges::copy(
original
| std::ranges::views::transform([](char c){return std::toupper(c);}),
std::back_inserter(upper)
);
Run Code Online (Sandbox Code Playgroud)
是完全有效的代码,旨在工作。这是由于 clang 过于急切地检查某些概念造成的(请参阅错误 47509)。我认为还有另一个错误报告,只是暂时找不到。
最终ranges::to将采用 from range-v3,因此预期的惯用结构将是:
std::string upper =
original
| std::ranges::views::transform([](char c){return std::toupper(c);}),
| std::ranges::to<std::string>();
Run Code Online (Sandbox Code Playgroud)
在此之前,您可以将 range-v3 用于to.