我知道C ++重量级人物正致力于将范围纳入语言,或者至少是标准库:
公平地说 - 我还没有通读官方建议。我只是一个想要使用简单范围功能的谦虚的C ++程序员。我应该做什么今天而不是在C ++ 17之后使用,比方说,带有步幅的简单整数范围?当然,当我开始实际使用范围时,我的要求可能会扩大,但我仍然没有追求更高级的东西以及各种各样的角落情况。我想。
在限制性更强的一面,由于兼容性需求(CUDA),我正在处理一个有点旧的环境,因此我需要使用GCC 4.9.3及其相应的标准库版本,以及我可以使用的东西GPU代码(不一定是相同的库/标题,但希望是相同的)。
那么,我应该推出自己的有限功能整数范围类型,等待手续解决 - 或者我应该选择更重量级的替代方案之一(Niebler' Ranges v3&# 34;,Boost irange等)?
答案 0 :(得分:3)
写一个简单的"索引" - 存储类型T
并通过副本返回类型O=T
的输入迭代器很容易。
我称之为index
的是一个迭代器,它包含支持进度和比较(包括其他迭代器和类似整数的东西)的东西,并在取消引用时返回包含对象的副本。生成范围超过迭代器到范围也很有用。
template<class T, class O=T>
struct index_t:
std::iterator<
std::input_iterator_tag,
O, std::ptrdiff_t, O*, O
>
{
T t;
explicit index_t(T&& tin):t(std::move(tin)){}
explicit index_t(T const& tin):t(tin){}
index_t()=default;
index_t(index_t&&)=default;
index_t(index_t const&)=default;
index_t& operator=(index_t&&)=default;
index_t& operator=(index_t const&)=default;
O operator*()const{ return t; }
O operator*(){ return t; }
O const* operator->()const{ return &t; }
O* operator->(){ return &t; }
index_t& operator++(){ ++t; return *this; }
index_t operator++(int){ auto r = *this; ++*this; return r; }
friend bool operator==(index_t const& lhs, index_t const& rhs) {
return lhs.t == rhs.t;
}
friend bool operator!=(index_t const& lhs, index_t const& rhs) { return !(lhs==rhs); }
};
template<class Scalar>
index_t<Scalar> index_to( Scalar s ) {
return index_t<Scalar>(std::move(s));
}
或某些人。 index_t<int>
是一个无步幅的整数迭代器。
如果我们想要步幅:
template<class T, class D=std::size_t>
struct strided {
T t;
D stride;
strided( T tin, D sin ):t(std::move(tin)), stride(std::move(sin)) {}
strided& operator++(){ t+=stride; return *this; }
strided operator++(int){ auto r = *this; ++*this; return r; }
operator T()&&{return std::move(t);}
operator T() const &{return t;}
friend bool operator==(strided const& lhs, strided const& rhs){
return lhs.t == rhs.t;
}
friend bool operator!=(strided const& lhs, strided const& rhs) { return !(lhs==rhs); }
};
template<class T, class D=std::size_t>
using strided_index_t = index_t<strided<T,D>, T>;
现在你只需要写range_t<Iterator>
(开始,结束,空,前,后,构造函数)。
template<class T>
strided_index_t<T> strided_index_to( T t, std::size_t d ) {
return strided_index_t<T>( {std::move(t), d} );
}
template<class It>
struct range_t {
It b,e;
using element_type = decltype( *std::declval<It>() );
It begin() const { return b; }
It end() const { return e; }
bool empty() const { return begin()==end(); }
element_type front() const { return *begin(); }
element_type back() const { return *std::prev(end()); }
};
template<class It>
range_t<It> range(It b, It e){
return {std::move(b), std::move(e)};
}
现在我们可以制作索引范围:
template<class Scalar>
range_t<index_t<Scalar>> index_range( Scalar b, Scalar e ) {
return range( index_to(std::move(b)), index_to(std::move(e)) );
}
template<class Scalar>
range_t<strided_index_t<Scalar>> strided_index_range( Scalar b, Scalar e, std::size_t d ) {
return range( strided_index_to(std::move(b), d), strided_index_to(std::move(e), d) );
}
现在我们测试:
for (int i : index_range(0, 10))
std::cout << i << '\n';
for (int i : strided_index_range(0, 10, 2))
std::cout << i << '\n';
boost
和其他基于范围的库中也存在类似的对象。
顺便说一下,
for( auto it : index_to( begin(vec), end(vec) ) )
以基于范围的方式迭代vec
的迭代器。写
for( auto it : iterators_into(vec) )
也很容易。