2013-03-30 61 views
4

我正在嘗試將迭代器返回到過濾範圍中的最大元素。以下是我迄今爲止: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; 
} 

我預期的代碼中有最大元素的矢量x打印出來的指標(即2),但遺憾的是它不編譯(Linux的64位,GCC 4.7 .2),問題在上面指出的線上。我從編譯器中得到的第一個編譯錯誤如下:

/boost/tuple/detail/tuple_basic.hpp:396:36:錯誤:賦值只讀成員'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)。這是唯一的選擇嗎?謝謝。

+0

小心使用'using'指令:'namespace std'和'namespace boost :: lambda'都有像'_1'這樣的佔位符。 – TemplateRex

+1

@TemplateRex STL佔位符位於命名空間'std :: placeholders'中,因此在這種情況下不存在衝突。 –

回答

4

您遇到的特定錯誤出現,因爲boost lambda不是CopyAssignable。這裏有一個簡單的方法來達到同樣的消息:

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

如果提供CopyAssignable函子來filtered,boost.phoenix(你應該使用反正boost.lambda是走向棄用贊成鳳對),手寫結構或舊的忠實std::bind2nd(std::greater<double>(), 100),這條線與編譯鐺++:

bind2nd演示:http://liveworkspace.org/code/2xKZIf

鳳演示:http://liveworkspace.org/code/18425g

由於boost.concept檢查可能會導致gcc失敗,這可能是一個bug,但是由於filtered的結果是boost::filtered_range,它的迭代器沒有.index()成員函數,所以這是一個爭議點。

編輯在迴應評論: 比較迭代器到filtered_range與迭代器到原始向量將無法正常工作。不過,既然你用向量,因爲它仍然可以訪問,你可以比較的地址,因爲無論indexed也不filtered複印

#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一起壓縮),並通過所有轉換攜帶原始序列索引和值。

+0

我明白了,謝謝。我編輯了原文,以反映我使用boost :: function所做的更改。如果我將迭代器返回到最大元素,是否有方法檢查此迭代器是否在範圍內?將它與boost :: end(x)比較會給我另一個錯誤。 – linuxfever

+0

非常感謝Cubbi,它現在更清晰:) – linuxfever

相關問題