Rom*_*lov 23 c++ iterator initialization stdvector c++11
在许多语言中,有一些生成器可以帮助初始化集合.在C++中,如果想要统一初始化向量,可以编写:
std::vector<int> vec(10, 42); // get 10 elements, each equals 42
Run Code Online (Sandbox Code Playgroud)
如果想要动态生成不同的值,该怎么办?例如,用10个随机值或从0到9的连续数字初始化它?这种语法很方便,但在C++ 11中不起作用:
int cnt = 0;
std::vector<int> vec(10, [&cnt]()->int { return cnt++;});
Run Code Online (Sandbox Code Playgroud)
有没有一种通过迭代函数调用初始化集合的好方法?我目前使用这种丑陋的模式(没有比循环更可读/更短):
std::vector<int> vec;
int cnt = 0;
std::generate_n(std::back_inserter(vec), 10, [&cnt]()->int { return cnt++;});
Run Code Online (Sandbox Code Playgroud)
有一件事会有所帮助,它可以解释缺少第一个构造函数.我可以设想一个迭代器,它接受一个函数和一些调用,以便构造函数
vector ( InputIterator first, InputIterator last);
Run Code Online (Sandbox Code Playgroud)
适用.但我在标准库中找不到这样的东西.我错过了吗?还有另一个原因导致第一个构造函数没有达到标准吗?
Xeo*_*Xeo 15
可悲的是,没有标准设施可以做到这一点.
对于您的具体示例,您可以counting_iterator像这样使用Boost.Iterator :
std::vector<int> v(boost::counting_iterator<int>(0),
boost::counting_iterator<int>(10));
Run Code Online (Sandbox Code Playgroud)
或者甚至使用像这样的Boost.Range:
auto v(boost::copy_range<std::vector<int>>(boost::irange(0,10)));
Run Code Online (Sandbox Code Playgroud)
(copy_range基本上只是return std::vector<int>(begin(range), end(range))一个很好的方法,采用全范围构造来存在只支持带两个迭代器的范围构造的容器.)
现在,对于具有生成器功能(如std::rand)的通用情况,有function_input_iterator.递增时,它调用生成器并保存结果,然后在解除引用时返回结果.
#include <vector>
#include <iostream>
#include <cmath>
#include <boost/iterator/function_input_iterator.hpp>
int main(){
std::vector<int> v(boost::make_function_input_iterator(std::rand, 0),
boost::make_function_input_iterator(std::rand,10));
for(auto e : v)
std::cout << e << " ";
}
Run Code Online (Sandbox Code Playgroud)
遗憾的是,由于function_input_iterator不使用Boost.ResultOf,您需要一个函数指针或一个嵌套result_type的函数对象类型.无论出于何种原因,兰巴达都没有.您可以将lambda传递给std::function(或boost::function)对象,该对象定义了该对象.这是一个例子std::function.人们只能希望Boost.Iterator有一天会使用Boost.ResultOf,这将使用decltypeif BOOST_RESULT_OF_USE_DECLTYPE定义.
这个世界太大了,C++无法为所有东西提供解决方案.然而,C++并不想成为一个巨大的超市,为每一个可以想象的口味提供现成的饭菜.相反,它是一个小的,设备齐全的厨房中,你的C++大厨,可以编造任何你想要的解决方案.
这是序列生成器的一个愚蠢而粗糙的例子:
#include <iterator>
struct sequence_iterator : std::iterator<std::input_iterator_tag, int>
{
sequence_iterator() : singular(true) { }
sequence_iterator(int a, int b) : singular(false) start(a), end(b) { }
bool singular;
int start;
int end;
int operator*() { return start; }
void operator++() { ++start; }
bool operator==(sequence_iterator const & rhs) const
{
return (start == end) == rhs.singular;
}
bool operator!=(sequence_iterator const & rhs) const
{
return !operator==(rhs);
}
};
Run Code Online (Sandbox Code Playgroud)
现在你可以说:
std::vector<int> v(sequence_iterator(1,10), sequence_iterator());
Run Code Online (Sandbox Code Playgroud)
同样,你可以编写一个更通用的小工具,"调用给定的仿函数给定次数"等等(例如,通过模板化副本获取一个函数对象,并使用计数器作为重复计数器;并取消引用调用该仿函数).
| 归档时间: |
|
| 查看次数: |
5512 次 |
| 最近记录: |