C:boost :: rangeを使ってmax_elementを見つける方法は?

フィルター処理された範囲内で最大の要素にイテレーターを戻そうとしています。これが私がこれまでに持っているものです:

#include <boost/lambda/lambda.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <vector>
#include <iostream>

using namespace boost::adaptors;
using namespace boost::lambda;
using namespace std;

int main ()
{
  vector<double> x = {100, 150, 200, 110};
  auto it = boost::max_element(x | indexed(0) | filtered(_1>100)); /* problem here */
  cout << it.index() << endl;

  return 0;
}

私はコードが最大の要素(すなわち2)を持つベクトルxのインデックスを出力することを期待しました、しかし残念ながらそれはコンパイルされません(Linux 64bit、GCC 4.7.2)、問題は上に示された行にあります。私が(とりわけ)コンパイラから得た最初のコンパイルエラーは次のとおりです。

/boost/tuple/detail/tuple_basic.hpp:396:36:error:読み込み専用メンバーの割り当て ‘boost :: tuples :: cons :: head’

私が悪いことをしているという考えはありますか?それとも他にどのようにして私がやろうとしていることを達成することができますか?前もって感謝します!

編集:

問題のある行を次のように変更します。

auto it = boost::max_element<boost::return_found>(x | sliced(1,4) |   filtered(boost::function<bool(double)>(_1>100)));

反復子を最大の要素に戻すようです。しかし、反復子が範囲内にあることを確認する方法はありますか? boost :: end(x)と比較するとエラーになる。私が考えることができる唯一のことは戻ることです

auto another_range = boost::max_element<boost::return_found_end>(x | sliced(1,4) |   filtered(boost::function<bool(double)>(_1>100)));

そしてboost :: empty(another_range)をチェックする。これが唯一の選択肢ですか?ありがとう。

ベストアンサー
ブーストラムダはCopyAssignableではないため、発生した特定のエラーが表示されます。これは同じメッセージを達成するより簡単な方法です:

auto f1 = _1 > 100;
auto f2 = f1;
f2 = f1; // same error

フィルタされた、boost.phoenix(とにかく使うべきです、boost.lambdaはphoenixを支持するため廃止予定です)、手書きのstruct、または古い忠実なstd :: bind2nd()にCopyAssignableファンクタを提供する場合std :: greater< double>()、100)、この行はclangでコンパイルされます。

bind2ndデモ:http://liveworkspace.org/code/2xKZIf

フェニックスデモ:http://liveworkspace.org/code/18425g

boost.conceptチェックのためgccで失敗します。これはおそらくバグですが、filteredの結果がBoost :: filtered_rangeであり、そのイテレータに.index()メンバ関数がないため、問題になります。

コメントに対する編集:
イテレータとオリジナルのベクトルのイテレータをfiltered_rangeと比較してもうまくいきません。ただし、vectorを使用していて、まだアクセス可能なので、インデックスもフィルタも作成されていないので、アドレスを比較できます。

#include <vector>
#include <iostream>
#include <cassert>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/phoenix.hpp>

using namespace boost::adaptors;
using namespace boost::phoenix::placeholders;

int main ()
{
    std::vector<double> x = {100, 150, 200, 110};
    auto it = boost::max_element( x | indexed(0) | filtered(arg1 < 110) );
    assert(&x[0] <= &*it && &*it < &x[0] + x.size());
    std::cout << "Element " << *it << " is at index " << &*it - &x[0] << '\n';
}

デモhttp://liveworkspace.org/code/1zBIJ9

あるいは、より一般的な解決策としては、ベクトルをペアのベクトルに変換し(boostがzipアダプタを取得するとき、それをcounting_rangeできちんと圧縮することができます)、すべての変換を通して元のシーケンスインデックスを値とともに持ちます。

転載記事の出典を記入してください: C:boost :: rangeを使ってmax_elementを見つける方法は? - コードログ