对于以下代码:
#include <iostream>
#include <string>
#include <ranges>
int main()
{
std::string s = " text ";
auto sv = std::ranges::views::split(s, ' ');
std::cout << std::ranges::distance(sv.begin(), sv.end());
}
Run Code Online (Sandbox Code Playgroud)
输出为 2。输出范围中不存在最后一个分隔符之后的空子范围。
这似乎不一致,因为N+1如果N输入范围中出现分隔符,我希望输出范围中有子范围。为什么不是这样?
请注意 range-v3 做的完全一样,所以我确定这是故意的,但我想知道为什么。
我想<<为任何人写一个泛型,range最后我得到了这个:
std::ostream& operator << (std::ostream& out, std::ranges::range auto&& range) {
using namespace std::ranges;
if (empty(range)) {
return out << "[]";
}
auto current = begin(range);
out << '[' << *current;
while(++current != end(range)) {
out << ',' << *current;
}
return out << ']';
}
Run Code Online (Sandbox Code Playgroud)
像这样测试:
int main() {
std::vector<int> ints = {1, 2, 3, 4};
std::cout << ints << '\n';
}
Run Code Online (Sandbox Code Playgroud)
它完美运行并输出:
Run Code Online (Sandbox Code Playgroud)[1,2,3,4]
但是,当测试时:
int main() {
std::vector<int> empty = {};
std::cout << empty …Run Code Online (Sandbox Code Playgroud) 我开始尝试std::ranges并想了解视图是如何真正起作用的。所以我尝试编写自己的容器和迭代器类型,并希望在视图中使用它。
但是似乎缺少一些东西,但编译器只告诉我begin()视图中没有方法,但没有告诉我为什么。
例子:
#include <iostream>
#include <array>
#include <ranges>
class MyFixedContainer;
class MyIterator
{
MyFixedContainer* ptr;
unsigned int offset;
public:
MyIterator( MyFixedContainer* ptr_, unsigned int offset_ ): ptr{ ptr_},offset{offset_}{}
bool operator==( MyIterator& other ) const
{
return ( ptr == other.ptr )&& ( offset == other.offset );
}
bool operator!=( MyIterator& other ) const
{
return !(*this == other);
}
MyIterator operator++()
{
offset++;
return *this;
}
MyIterator operator++(int)
{
MyIterator tmp = *this;
offset++;
return …Run Code Online (Sandbox Code Playgroud) 使用范围允许我减少样板文件,所以这很好,但我找不到按升序或降序排序的方法。以下代码段编译得很好(g++ 10.2.0)并且投影确实简化了代码,不需要 lambda。
struct Player {
double score_;
string name_;
};
vector<Player> players{
{10.0, "Thorin"}, {20.0, "Bombur"}, {15.0, "Bofur"}, {5.0, "Bifur"},
{ 2.0, "Balin"}, {25.0, "Kili" }, {23.0, "Fili"}, {4.0, "Dwalin"}
};
std::ranges::sort(players, std::ranges::less{}, &Player::score_ );
for(auto const &player : players) {
cout << "Name = " << std::left << setw(10) << player.name_
<< " Score = " << player.score_ << endl;
}
Run Code Online (Sandbox Code Playgroud)
现在我需要一个布尔控制升序或降序排序。
我想写一个这样的简单语句:
std::ranges::sort(players, sort_ascending ? std::ranges::less() : std::ranges::greater() , &Player::score_);
Run Code Online (Sandbox Code Playgroud)
但是std::ranges::less和std::ranges::greater没有相同的类型,所以三元运算符将不起作用。
error: operands …Run Code Online (Sandbox Code Playgroud) In [range.sized#1]:
The
sized_rangeconcept refines range with the requirement that the number of elements in the range can be determined in amortized constant time usingranges?::?size.Run Code Online (Sandbox Code Playgroud)template<class T> concept sized_range = range<T> && requires(T& t) { ranges::size(t); };
The standard states that obtaining the size of ranges::sized_range is guaranteed to be in constant time. Consider the following:
auto r1 = std::views::iota(0)
| std::views::filter([](int x){ return x % 2 == 0; })
| std::views::take(1'000'000);
Run Code Online (Sandbox Code Playgroud)
r1 is obviously …
我正在使用带有 GCC 实现(v10.2 和 v11)的 C++20 范围。
为了测试行为的std::views::join,我试图生成使用嵌套视图single,然后我平坦它使用join。
#include <ranges>
#include <iostream>
int main() {
auto data = std::views::single(1);
auto v =
data
| std::views::transform([](const auto &s) { return std::views::single(s); })
| std::views::join
;
for (auto &&x : v) { // Infinite loop + segfault
std::cout << x << '\n';
}
}
Run Code Online (Sandbox Code Playgroud)
我希望找到for 的一个迭代器具有初始值 (1)循环。但是不......它进入了一个无限循环,因为我使用了这个值,所以出现了段错误。
如果我std::views::single用std::views::iota(a,b)或替换嵌套std::views::empty<int>,则行为完全没问题。
您知道这是否是正确的预期行为(以及为什么)?
编辑
std::ranges::next(v.begin()) == …
我知道sort范围内的算法(例如)支持投影,但在我看来,没有办法为视图获得该功能......我对吗?
作为示例,请考虑以下工作代码:
#include <algorithm>
#include <ranges>
#include <vector>
#include <iostream>
enum Color {
Red,
Green,
Blue
};
struct Cat {
int age;
Color color;
};
int main() {
std::vector<Cat> cats{{.age = 10,.color=Color::Red}, {.age = 20,.color=Color::Blue}, {.age = 30,.color=Color::Green}};
auto is_red = [](const auto& cat) {return cat.color == Color::Red;};
for (const auto& cat: cats | std::views::filter(is_red)) {
std::cout << cat.age << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法删除 lambda 并执行以下操作:
for (const auto& cat: cats | std::views::filter(&Cat::color, Color::Red) {
Run Code Online (Sandbox Code Playgroud)
注意:我的问题是成员变量投影,但显然在实际代码中也需要成员函数调用。
考虑Point带有x,y和z值的类型。如果我有一系列Point对象,例如std::vector<Point>,我需要添加什么Point才能使其与std::ranges::views::elements范围适配器一起使用?
目的是做类似的事情
std::vector<Point> v{...};
for (auto x : v | std::ranges::views::elements<0>) {
// do something with all `x` values
}
Run Code Online (Sandbox Code Playgroud)
该文档提到std::ranges::views::elements适用于“类似元组”的值。我假设它的工作方式应该类似于我们如何使我们的类型与结构化绑定一起工作,但我似乎遗漏了一些东西
我已尝试使用以下代码
class Point {
double x=0;
double y=0;
double z=0;
public:
Point(double x, double y, double z) : x(x), y(y), z(z) {}
template <std::size_t N>
double get() const {
if constexpr(N == 0)
return x;
else if …Run Code Online (Sandbox Code Playgroud) 为什么有std::lexicographical_compare_three_way,却没有std::ranges::lexicographical_compare_three_way?
中有参数 Comp std::ranges::lexicographical_compare,但它相当无用,因为bool当需要比较类别类型之一时,函数返回 。
以下是 cppref 的一些链接
https://en.cppreference.com/w/cpp/algorithm/lexicographyal_compare_ Three_way
https://en.cppreference.com/w/cpp/algorithm/ranges/lexicographyal_compare
奇怪行为的常见示例views::filter:
#include <iostream>
#include <ranges>
#include <vector>
int main ()
{
using namespace std;
auto ml = [](char c) // ml = make lambda (always accepts / transforms to 1)
{
return [c](int) {cout << c; return 1;};
};
vector<int> vec = {1};
auto view = vec
| views::transform (ml('T'))
| views::filter (ml('F'));
// use view somehow:
return *view.begin();
}
Run Code Online (Sandbox Code Playgroud)
哪个输出TFT(注意额外的T)。演示
我们必须知道:
auto view = vec
| views::transform (ml('A'))
| views::filter (ml('B'));
Run Code Online (Sandbox Code Playgroud)
...只是语法糖: …