我试图理解,yield 系列函数要求该类默认可构造的原因是什么?
在以下示例中,仅当 CNum 具有默认构造函数时,vnums1 行才会编译。vnums2 行不需要默认构造函数。
我正在使用 Visual Studio 2017 和 Range-V3-VS2015。谢谢你!
#include <range/v3/all.hpp>
struct CNum
{
// CNum() = default;
explicit CNum(int num) : m_num(num) {}
int m_num;
};
int main()
{
auto ints = ranges::view::ints(0, 10);
// this compiles only of CNum has a default constructor
auto vnums1 = ints
| ranges::view::for_each([](int num) { return ranges::yield_if(num % 2, CNum(num)); })
| ranges::to_vector;
// this compiles even if CNum does not have a default constructor
auto vnums2 = …Run Code Online (Sandbox Code Playgroud) 如果我有两个(或更多)向量,我可以将zip它们组合在一起,range-v3如下所示:
std::vector< int > v1{1,1,1};
std::vector< int > v2{2,2,2};
auto v = ranges::views::zip( v1, v2 )
| ranges::views::transform( ... );
Run Code Online (Sandbox Code Playgroud)
这很有效,但实际上,我没有显式向量,但我确实有向量的向量。我想做以下事情,但它没有给出相同的结果。(其实我不确定结果是什么,也不知道如何确定结果是什么!)
std::vector< std::vector< int > > V{{1,1,1},{2,2,2}};
auto vV = ranges::views::zip( V )
| ranges::views::transform( ... );
Run Code Online (Sandbox Code Playgroud)
我该怎么做才能vector< vector >像压缩一些显式向量一样压缩 a ?我尝试过join与stride、chunk等一起使用,但还没有找到神奇的组合。
我怀疑这accumulate不是唯一没有成功的算法。
也许现在有更好的方法来在一个范围内执行累积(折叠),因此accumulate已经过时了?
我发现c++20与range-v3ranges::basic_istream_view版本略有不同。
最重要的区别是std::ranges::basic_istream_view不会缓存其begin(),因此每个begin()s 将返回具有已读取值的下一个迭代器(godbolt):
auto words = std::istringstream{"today is yesterday's tomorrow"};
auto view = std::ranges::istream_view<std::string>(words);
std::cout << *view.begin() << "\n"; // today
std::cout << *view.begin() << "\n"; // is
std::cout << *view.begin() << "\n"; // yesterday's
std::cout << *view.begin() << "\n"; // tomorrow
Run Code Online (Sandbox Code Playgroud)
考虑以下内容(godbolt),如果我使用 range-v3 版本,则所有三个std::ranges::find()s 都会找到"is",但如果我使用 std 版本,"is"则只会在第一次调用中找到。
auto words = std::istringstream{"today is yesterday's tomorrow"};
auto view = std::ranges::istream_view<std::string>(words);
std::cout << …Run Code Online (Sandbox Code Playgroud) 我发现大多数 C++ stl 算法的传统语法很烦人;使用它们编写起来很长只是一个小问题,但它们总是需要对现有对象进行操作,这在很大程度上限制了它们的可组合性。
我很高兴看到 stl 中范围的出现;然而,从 C++20 开始,存在严重的缺点:标准库的不同实现对此的支持各不相同,并且 range-v3 中存在的许多内容并未进入 C++20,例如(对我来说)非常令人惊讶),将视图转换为向量(对我来说,如果我无法将计算结果存储在向量中,这会使这一切变得毫无用处)。
另一方面,使用 range-v3 对我来说似乎也不理想:它的文档很少(而且我不同意其中的所有内容都是不言自明的),而且更严重的是,C++20 的想法range 与 range-v3 所做的不同,所以我不能只是说,好吧,让我们坚持使用 range-v3;无论如何,这将在某个时候成为标准。
那么,我应该使用两者中的任何一个吗?或者这一切都不值得,并且通过依赖 std 范围或 range-v3,使我的代码太难以维护和移植?
我想得到名字以'T'开头的人数:
#include <iostream>
#include <string>
#include <range\v3\all.hpp>
using namespace ranges;
int main()
{
const auto names = std::vector<std::string> {"Tony", "Peter"};
std::cout << size(names | view::filter([](const auto& s) {return s[0] == 'T';}));
}
Run Code Online (Sandbox Code Playgroud)
但我得到了巨大的编译错误:
? clang -std=c++14 test.cpp
test.cpp:11:18: error: no matching function for call to object of type 'const ranges::v3::adl_size_detail::size_fn'
std::cout << size(names | view::filter([](const auto& s) {return s[0] == 'T';}));
^~~~
K:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\range/v3/size.hpp:90:32: note: candidate template
ignored: substitution failure [with Rng =
ranges::v3::remove_if_view<ranges::v3::iterator_range<std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<std::basic_string<char,
std::char_traits<char>, std::allocator<char> …Run Code Online (Sandbox Code Playgroud) 试图学习如何使用Eric Niebler的range-v3库,并阅读源代码,我看到了宏定义:
#define CONCEPT_PP_CAT_(X, Y) X ## Y
#define CONCEPT_PP_CAT(X, Y) CONCEPT_PP_CAT_(X, Y)
/// \addtogroup group-concepts
/// @{
#define CONCEPT_REQUIRES_(...) \
int CONCEPT_PP_CAT(_concept_requires_, __LINE__) = 42, \
typename std::enable_if< \
(CONCEPT_PP_CAT(_concept_requires_, __LINE__) == 43) || (__VA_ARGS__), \
int \
>::type = 0 \
/**/
Run Code Online (Sandbox Code Playgroud)
简而言之,模板定义如下:
template<typename I, typename O,
CONCEPT_REQUIRES_(InputIterator<I>() &&
WeaklyIncrementable<O>())>
void fun_signature() {}
Run Code Online (Sandbox Code Playgroud)
翻译为:
template<typename I, typename O,
int a_unique_name = 42,
typename std::enable_if
<false || (InputIterator<I>() &&
WeaklyIncrementable<O>()), int>::type = 0
>
void fun_signature() {}
Run Code Online (Sandbox Code Playgroud)
我想知道为什么宏实现这种方式.为什么需要这个整数,为什么它需要一个false …
由于在c ++ 17中没有基于索引的算法并行,我想知道是否可以结合使用来模拟。那是:ranges::view::iotastd::for_each
using namespace std;
constexpr int N= 10'000'000;
ranges::iota_view indices(0,N);
vector<int> v(N);
for_each(execution::par_unseq,indices.begin(),indices.end(),[&](int i) { v[i]= i; });
Run Code Online (Sandbox Code Playgroud)
iota_view似乎提供了对适当类型的随机访问([range.iota.iterator]):
iota_view<I, Bound>::iterator::iterator_category定义如下:(1.1) -如果
I模型Advanceable,然后iterator_category是random_access_iterator_tag。(1.2) -否则,如果
I模型Decrementable,然后iterator_category是bidirectional_iterator_tag。(1.3) -否则,如果
I模型Incrementable,然后iterator_category是forward_iterator_tag。(1.4)-否则
iterator_category为input_iterator_tag。
上面的代码正确吗?使用iota_view这种方式是否会降低性能?
编辑:我已经使用range-v3,cmcstl2和Intel的PSTL进行了一些测试。
使用range-v3,以上示例无法使用GCC …
#include <vector>
#include <algorithm>
#include <range/v3/all.hpp>
using namespace ranges;
int main()
{
auto coll = std::vector{ 1, 2, 3 };
std::for_each(coll.begin(), coll.end(), [](auto){}); // ok
coll | view::for_each([](auto){}); // static_assert failure
}
Run Code Online (Sandbox Code Playgroud)
该static_assert错误消息:
要使用view :: for_each,函数F必须返回InputRange概念的模型.
std::for_each需要一个返回的仿函数void,为什么ranges::view::for_each要求仿函数必须返回一个InputRange概念模型?
将7x5矩阵展平为std :: vector,我想使用Eric Niebler的range-v3库获取列和行的视图.到目前为止,我管理(改进的空间)以获得单行,单列和连接行的视图.
请参阅:https://wandbox.org/permlink/8o4RgSucF3zSNuPN
std::vector<int> numbers = {
00, 01, 02, 03, 04,
10, 11, 12, 13, 14,
20, 21, 22, 23, 24,
30, 31, 32, 33, 34,
40, 41, 42, 43, 44,
50, 51, 52, 53, 54,
60, 61, 62, 63, 64,
};
const size_t n = 5;//number of columns
//Row_3 = {30, 31, 32, 33, 34}
auto Row_3 = numbers | GetRow(3, n);
std::cout << Row_3 << std::endl;
//Col_2 = {02, 12, 22, 32, …Run Code Online (Sandbox Code Playgroud)