目标是这样的语法:
std::vector<Object*> v1 = generate([](auto&&){ return new Object; }, 10).make_container();
我们说我们要生成 10 个具有特定 lambda 的元素,然后我们创建一个请求类型的容器。
它需要一些样板文件。首先是一个输入迭代器,对一个函数进行计数和调用:
template<class F>
struct generator_iterator {
F f;
std::size_t i = 0;
using self=generator_iterator;
friend bool operator==(self const& lhs, self const& rhs){ return lhs.i==rhs.i; }
friend bool operator!=(self const& lhs, self const& rhs){ return lhs.i!=rhs.i; }
using reference=std::result_of_t<F const&(std::size_t const&)>;
using value_type=std::decay_t<reference>;
using difference_type=std::ptrdiff_t;
using pointer=value_type*;
using iterator_category=std::input_iterator_tag;
self& operator++(){++i; return *this;}
self operator++(int){auto tmp=*this; ++*this; return tmp;}
reference operator*()const{ return f(i); }
pointer operator->()const { return std::addressof(f(i)); }
friend difference_type operator-( self const& lhs, self const& rhs ) { return lhs.i-rhs.i; }
self& operator-=( difference_type rhs )& {
i-=rhs;
return *this;
}
self& operator+=( difference_type rhs )& {
i+=rhs;
return *this;
}
friend difference_type operator+( self lhs, difference_type rhs ) {
lhs += rhs;
return lhs;
}
friend difference_type operator-( self lhs, difference_type rhs ) {
lhs -= rhs;
return lhs;
}
};
接下来,一个范围原语,带有一个.make_container() 方法,可让您通过显式或隐式传递类型将范围转换为容器:
template<class It>
struct range_t {
It b, e;
It begin() const { return b; }
It end() const { return e; }
private:
struct container_maker {
range_t const* self;
template<class C>
operator C()&& {
return {self->begin(), self->end()};
}
};
public:
container_maker make_container()const{
return {this};
}
// C is optional
template<class C>
C make_container()const{
return make_container();
}
};
template<class It>
range_t<It> range( It s, It f ) {
return {std::move(s), std::move(f)};
}
然后我们将它们粘合在一起:
template<class F>
auto generate( F&& f, std::size_t count ) {
generator_iterator<std::decay_t<F>> e{f, count};
generator_iterator<std::decay_t<F>> b{std::forward<F>(f)};
return range( std::move(b), std::move(e) );
}
然后编译:
std::vector<Object*> v1 = generate([](auto&&){ return new Object; }, 10).make_container();
Live example.