#include <vector>
#include <iostream>
#include <range/v3/all.hpp>
int main()
{
auto coll = std::vector{ 1, 2, 3 };
ranges::copy(
coll,
ranges::ostream_iterator<int>{ std::cout, ", " }
); // ok
ranges::copy(
coll,
std::ostream_iterator<int>{ std::cout, ", " }
); // error
}
Run Code Online (Sandbox Code Playgroud)
问题显示在上面的代码中.我使用range-v3-0.3.7.
对我来说,通用算法copy不应该关心目标迭代器类型,只要它满足输出迭代器的要求即可.
如果是这样,为什么范围的算法不与std的迭代器兼容?
给定一对传统的“开始”和“结束”迭代器,如何创建与 range-v3 兼容的范围?
假设我正在编写一个接受两个迭代器的通用函数,以便与遗留代码兼容。
struct result;
bool keep_line(const std::string&);
result parse_line(const std::string&);
template <typename InputIt>
std::vector<result> parse_lines(InputIt begin, InputIt end)
{
// This is what I want to do...
auto lines = ranges::make_range_out_of_legacy_iterators(begin, end);
return lines
| ranges::view::filter(keep_line)
| ranges::view::transform(parse_line)
| ranges::to<std::vector<result>>();
}
Run Code Online (Sandbox Code Playgroud) 范围将随着 C++20 标准版本进入 C++。
我的问题:我们是否能够构建(现有)任何范围的标准库容器?更重要的是,具有范围视图?
例如,这会不会:
#include <vector>
#include <iostream>
#include <ranges>
int main() {
auto sq = [](int x) { return x * x; };
std::vector<int> vec { 3, 4, 5 };
std::vector<int> squares { std::ranges::views::transform(vec, sq) };
for(auto i : squares) { std::cout << i << ' '; }
std::cout << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
是一个打印的有效程序9 16 25?
这与 range-v3 库一起编译,这是值得的。
Range-v3 具有ranges::views::drop和 来ranges::views::drop_last从视图的前面或后面删除元素。
它是否提供类似的功能来将元素添加到视图中?
目前,我发现的最短方法是使用 a或 a到concat范围/容器:iotasingle
#include <assert.h>
#include <range/v3/view/iota.hpp>
#include <range/v3/view/concat.hpp>
#include <range/v3/to_container.hpp>
using namespace ranges;
using namespace views;
int main() {
std::vector<int> v{1,2,3};
auto wi = concat(iota(0,1),v);
assert(((wi | to_vector) == std::vector<int>{0,1,2,3}));
auto ws = concat(single(0), v);
assert(((ws | to_vector) == std::vector<int>{0,1,2,3}));
}
Run Code Online (Sandbox Code Playgroud) 在Eric Niebler的range-v3库中,他提供了许多标题,每个标题都有自己的全局函数对象.他们都以同样的方式宣布.他提供了一个类模板static_const:
template<typename T>
struct static_const
{
static constexpr T value {};
};
template<typename T>
constexpr T static_const<T>::value;
Run Code Online (Sandbox Code Playgroud)
然后将类型的每个函数对象F声明为:
namespace
{
constexpr auto&& f = static_const<F>::value;
}
Run Code Online (Sandbox Code Playgroud)
通过static_const模板和未命名的命名空间引入对象有什么好处,而不是只写:
static constexpr F f{};
Run Code Online (Sandbox Code Playgroud) 在range-v3中,所有函数都是内联命名空间中的全局函数对象:
Run Code Online (Sandbox Code Playgroud)#if RANGES_CXX_INLINE_VARIABLES < RANGES_CXX_INLINE_VARIABLES_17 #define RANGES_INLINE_VARIABLE(type, name) \ inline namespace function_objects \ { \ inline namespace \ { \ constexpr auto &name = ::ranges::static_const<type>::value; \ } \ } #else // RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17 #define RANGES_INLINE_VARIABLE(type, name) \ inline namespace function_objects \ { \ inline constexpr type name{}; \ } #endif // RANGES_CXX_INLINE_VARIABLES
function_objects命名空间的目的是什么?据我所知,它不会在库中的任何其他位置引用.
我正在学习C ++ 20范围(使用Range-V3-VS2015)。我有这段代码可以正常工作:
string clean;
auto tmp1 = input | view::remove_if(not_alpha) | view::transform(::tolower);
std::copy(tmp1.begin(), tmp1.end(), std::back_inserter(clean));
auto tmp2 = clean |= action::sort | action::unique;
Run Code Online (Sandbox Code Playgroud)
不过,我想这两个管道定义结合tmp1并tmp2成一个单一的管道。那可能吗?我已经尝试了无数次尝试,包括添加view::move和添加在内view::copy。
我正在使用范围库来帮助我的类中的文件管理器数据,如下所示:
class MyClass
{
public:
MyClass(std::vector<int> v) : vec(v) {}
std::vector<int> getEvens() const
{
auto evens = vec | ranges::views::filter([](int i) { return ! (i % 2); });
return std::vector<int>(evens.begin(), evens.end());
}
private:
std::vector<int> vec;
};
Run Code Online (Sandbox Code Playgroud)
在这种情况下,函数中构造了一个新向量getEvents()。为了节省这种开销,我想知道是否可以/建议直接从函数返回范围?
class MyClass
{
public:
using RangeReturnType = ???;
MyClass(std::vector<int> v) : vec(v) {}
RangeReturnType getEvens() const
{
auto evens = vec | ranges::views::filter([](int i) { return ! (i % 2); });
// ...
return evens;
}
private:
std::vector<int> vec;
};
Run Code Online (Sandbox Code Playgroud)
如果可能的话,我是否需要考虑任何终生注意事项? …
假设我们有一个 s 数组std::pair:
using Particle = std::pair<std::string, double>;
Particle particles[] {{"Electron", 0.511}, {"Muon", 105.66}, {"Tau", 1776.86}};
Run Code Online (Sandbox Code Playgroud)
我们可以使用具有不同投影函数的C++20范围算法来根据不同的数据成员对它们进行排序:
ranges::sort(particles, {}, &Particle::first);
ranges::sort(particles, {}, &Particle::second);
Run Code Online (Sandbox Code Playgroud)
这看起来非常干净。但是当我将Particle的数据类型移至std::tuple:
using Particle = std::tuple<std::string, double>;
Run Code Online (Sandbox Code Playgroud)
我不能再使用相同的投影度量,因为std::tuple没有first或second没有成员。或者,只需传递 lambda 即可正常工作:
ranges::sort(particles, {}, [](const auto& t) { return std::get<0>(t); });
ranges::sort(particles, {}, [](const auto& t) { return std::get<1>(t); });
Run Code Online (Sandbox Code Playgroud)
但是有没有更简洁的项目方法可以做到这一点?
ranges::sort(particles, {}, &std::get<0>);
Run Code Online (Sandbox Code Playgroud) 我想声明一个函数,它获取一个范围作为输入,输出一个数字并将其直接与 range-v3 库的 range::views::transform 一起使用。
以下内容有效,但我必须使用一个实际上不做任何事情的 lambda。
int64_t getGroupValue( ranges::input_range auto&& group ) {
return ranges::accumulate( group, 1ll, ranges::multiplies() );
}
int64_t calculateGroupSum( const std::vector<int>& data ) {
using ranges::views::transform;
using ranges::views::chunk;
return ranges::accumulate(
data
| chunk( 3 )
| transform( [] ( auto group ) { return getGroupValue( group ); })
, 0ll);
}
Run Code Online (Sandbox Code Playgroud)
我想做以下事情:
int64_t calculateGroupSum( const std::vector<int>& data ) {
using ranges::views::transform;
using ranges::views::chunk;
return ranges::accumulate(
data
| chunk( 3 )
| transform( getGroupValue )
, 0ll); …Run Code Online (Sandbox Code Playgroud)