本の虫: Dwangoプログラミングコンテストの感想で固定回のループがあればいいと書いたが、range-based forにそういうイテレーターを与えてやればいいのではないかと気がついた。つまり、こういうことだ。
class counter_iterator
{
std::size_t i ;
public :
counter_iterator() : i(0) { }
counter_iterator( std::size_t n ) : i(n) { }
bool operator == ( const counter_iterator & rhs ) const
{
return i == rhs.i ;
}
bool operator != ( const counter_iterator & rhs ) const
{
return i != rhs.i ;
}
std::size_t & operator * ( )
{
return i ;
}
counter_iterator & operator ++ ()
{
++i ;
return *this ;
}
} ;
class nth_loop
{
private :
std::size_t i ;
public :
nth_loop( std::size_t n ) : i(n) { }
counter_iterator begin() const
{
return counter_iterator() ;
}
counter_iterator end() const
{
return counter_iterator(i) ;
}
} ;
nth_loop rep( std::size_t n )
{
return nth_loop( n ) ;
}
int main()
{
for ( auto elem : rep(10) )
{
std::cout << elem << std::endl ;
}
}
とはいえ、for ( elem : 10 )と書きたいところだ。
追記:ユーザー定義リテラルを使う方法を思いついた。unsigned long long intに書き変えるのは省略。
nth_loop operator "" _( unsigned long long int n )
{
return nth_loop( n ) ;
}
int main()
{
for ( auto i : 10_ )
{
std::cout << i << std::endl ;
}
}
だいぶ簡略化された。
なお、Boostに同等のライブラリ、boost::iragenがある。
ドワンゴ広告
ドワンゴは本物のC++プログラマーを募集しています。
CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0
これいいですね。
ReplyDelete自分の職権活用して提案してみたらいかがですか?
ttp://ideone.com/uyUPNo
ReplyDeleteこういうコードを書いてみました。
クラスを一つ除去できたかわりに汚いです。
もっとましなの標準に提案してくださいお願いします。
このコードは高橋氏のページを参考に作りました。
s/boost::iragen/boost::irange/
ReplyDeleteboost::irangeはSTLアルゴリズムでインデックスのレンジが欲しいときに使っています.
ReplyDeleteしかし,その内部的な挙動のせいか,コンパイラの最適化が効きにくいようです.私の環境では,GCC 4.9だと最適化を-O3くらいに強くしないと単純なfor loopより遅くなりました.あとGCCのparallel mode(まだexperimentalですが)も,irangeを使ったアルゴリズムは上手く並列化できないようです.
このあたりはコンパイラの問題なのかもしれませんが,インデックスに対する反復は基本的な機能ですし,STLアルゴリズムと組み合わせた時の最適化まで考慮したインデックスレンジが標準に欲しいものです.