2012-10-01 18 views
12

Tôi đang cố gắng sử dụng boost :: adapters :: được chuyển đổi bằng cách cung cấp lambda C++ 0x cho adapter.boost transformator iterator và C++ 11 lambda

Mã sau đây không biên dịch. Tôi đang sử dụng g ++ 4.6.2 với tăng 1.48.

#include <iostream> 
#include <vector> 

#include <boost/range/adaptors.hpp> 
#include <boost/range/algorithm.hpp> 

using namespace std; 
namespace br = boost::range; 
namespace badpt = boost::adaptors; 


int main() 
{ 
    vector<int> a = {0,3,1,}; 
    vector<int> b = {100,200,300,400}; 

    auto my_ftor = [&b](int r)->int{return b[r];}; 

    cout<<*br::max_element(a|badpt::transformed(my_ftor))<<endl; 
} 

Mọi ý tưởng về những gì tôi đang làm sai ở đây?

+0

Bạn gặp phải lỗi gì? – ronag

+0

http://stackoverflow.com/questions/12672372/boost-transform-iterator-and-c11-lambda có liên quan và mb dup. – ForEveR

+0

Nhật ký lỗi được chi tiết. Vui lòng xem [link] (http://pastebin.com/grsENb1m). – Nithin

Trả lời

4

Vâng lambdas không chơi đẹp, vì chúng không phải là cấu hình mặc định, cần thiết cho trình lặp. Đây là một wrapper tôi sử dụng cho lambdas:

#define RETURNS(...) -> decltype(__VA_ARGS__) { return (__VA_ARGS__); } 

template<class Fun> 
struct function_object 
{ 
    boost::optional<Fun> f; 

    function_object() 
    {} 
    function_object(Fun f): f(f) 
    {} 

    function_object(const function_object & rhs) : f(rhs.f) 
    {} 

    // Assignment operator is just a copy construction, which does not provide 
    // the strong exception guarantee. 
    function_object& operator=(const function_object& rhs) 
    { 
     if (this != &rhs) 
     { 
      this->~function_object(); 
      new (this) function_object(rhs); 
     } 
     return *this; 
    } 

    template<class F> 
    struct result 
    {}; 

    template<class F, class T> 
    struct result<F(T)> 
    { 
     typedef decltype(std::declval<Fun>()(std::declval<T>())) type; 
    }; 

    template<class T> 
    auto operator()(T && x) const RETURNS((*f)(std::forward<T>(x))) 

    template<class T> 
    auto operator()(T && x) RETURNS((*f)(std::forward<T>(x))) 
}; 

template<class F> 
function_object<F> make_function_object(F f) 
{ 
    return function_object<F>(f); 
} 

Sau đó, bạn chỉ có thể làm điều này:

int main() 
{ 
    vector<int> a = {0,3,1,}; 
    vector<int> b = {100,200,300,400}; 

    cout<<*br::max_element(a|badpt::transformed(make_function_object([&b](int r)->int{return b[r];};)))<<endl; 
} 
8

Vấn đề nổi tiếng. Nhìn đây

http://boost.2283326.n4.nabble.com/range-cannot-use-lambda-predicate-in-adaptor-with-certain-algorithms-td3560157.html

thời gian ngắn, bạn nên sử dụng macro

#define BOOST_RESULT_OF_USE_DECLTYPE 

này để sử dụng decltype thay vì boost::result_of.

Trích từ here

Nếu trình biên dịch của bạn hỗ trợ decltype, sau đó bạn có thể kích hoạt tự động khấu trừ loại kết quả bằng cách xác định vĩ mô BOOST_RESULT_OF_USE_DECLTYPE, như trong ví dụ sau.

+1

Xin chào, tôi hiểu, điều này có thể áp dụng để tăng 1.51 +. Tôi đã thử chèn macro trước khi bất kỳ tiêu đề tăng nào được bao gồm nhưng nó không có hiệu lực. Các giải pháp khác trong liên kết cũng cho biết tính khả dụng của boost/range/regular.hpp không có sẵn trong boost-1.48. Cảm ơn các liên kết. – Nithin

+1

@Nithin macro này sửa nhiều lỗi hơn, nhưng có lỗi, không thể sửa mà không tăng :: viết lại phạm vi (xây dựng functor theo mặc định c-tor (phiên bản tăng 1.48) chẳng hạn sẽ không bao giờ làm việc với đóng). Không sử dụng bao đóng với tăng :: transform_iterator bây giờ – ForEveR

+0

Oh well! Cảm ơn các đầu vào. Tôi có thể sẽ đi với gợi ý @Paul vì tôi thực sự không thể thay đổi phiên bản tăng cường ngay bây giờ. – Nithin

1

@ câu trả lời của Forever (#define BOOST_RESULT_OF_USE_DECLTYPE) không làm việc cho tôi. Và câu trả lời của @ Paul quá dài (và quá chung chung). Một giải pháp cụ thể hơn có thể là thế này:

#include <iostream> 
#include <vector> 

#include <boost/range/adaptors.hpp> 
#include <boost/range/algorithm.hpp> 

using namespace std; 
namespace br = boost::range; 
namespace badpt = boost::adaptors; 


int main() 
{ 
    vector<int> a = {0,3,1,}; 
    vector<int> b = {100,200,300,400}; 

    struct{ 
    vector<int>* bP;        //pointer, just to imitate lambda syntax... 
    int operator()(int r) const{return (*bP)[r];} //was my_ftor = [&b](int r)->int{return b[r];}; 
    } my_ftor{&b};         //...here 

    cout<<*br::max_element(a|badpt::transformed(my_ftor))<<endl; 
} 

(Đó là năm 2016, Tăng 1,58 và điều này vẫn còn bị hỏng Ít nhất lambda mà không chụp nên thực hiện đầy đủ các yêu cầu của boost::transformed..)

Nếu lambda didn Không có ảnh chụp (không phải trường hợp của bạn) mã sẽ đơn giản hơn một chút HOẶC bạn có thể sử dụng: