【Range】 invalid initialization of non-const type with adaptors
これがコンパイル通らない。
(一時オブジェクトを左辺値参照に束縛できてしまうVC++では言語拡張をOFFにすること)
#include <vector> #include <boost/range/algorithm/fill.hpp> #include <boost/range/adaptor/reversed.hpp> int main() { std::vector<int> v(10); boost::fill(v | boost::adaptors::reversed, 1); // エラー! }
コンパイルが通らない理由は、boost::fillが以下のようにForwardRangeの左辺値参照を引数にとるため、Rangeアダプタの適用結果として返されるiterator rangeの一時オブジェクトを左辺値として扱えないから。
template< class ForwardRange, class Value > inline ForwardRange& fill(ForwardRange& rng, const Value& val);
Ovenではコンパイルが通り、動作もするが、Rangeアダプタの適用結果をMutable Algorithmに渡すようなケースはあまりないかもしれない。
#include <vector> #include <pstade/oven/algorithm.hpp> #include <pstade/oven/reversed.hpp> namespace oven = pstade::oven; int main() { std::vector<int> v(10); oven::fill(v | oven::reversed, 1); // OK }
ちなみに、RangeExでこういったケースに対応するには、Rangeアダプタの適用結果を非constの一時変数に格納してからMutable Algorithmに渡すか、Boost.Foreachを使え、とのこと。
#include <vector> #include <boost/typeof/typeof.hpp> #include <boost/range/algorithm/fill.hpp> #include <boost/range/adaptor/reversed.hpp> int main() { std::vector<int> v(10); BOOST_AUTO(r, (v | boost::adaptors::reversed)); boost::fill(r, 1); // OK }
#include <vector> #include <boost/foreach.hpp> #include <boost/range/adaptor/reversed.hpp> int main() { std::vector<int> v(10); BOOST_FOREACH (int& x, v | boost::adaptors::reversed) { x = 1; // OK } }