12

私は、アダプターにc++0xラムダを提供することによってboost::adapters::transformedを使用しようとしています。

次のコードはコンパイルされません。私はブースト1.48でg++4.6.2を使用しています。

#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;
}

私がここで間違っていることについて何か考えはありますか?

4

3 に答える 3

9

これはよく知られている問題です。ここを見て

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

まもなく、このマクロを使用する必要があります

#define BOOST_RESULT_OF_USE_DECLTYPE

decltypeの代わりに使用しますboost::result_of

ここから引用

コンパイラがdecltypeをサポートしている場合は、次の例のように、マクロBOOST_RESULT_OF_USE_DECLTYPEを定義することにより、結果タイプの自動推定を有効にできます。

于 2012-10-01T11:47:56.323 に答える
4

ラムダはデフォルトで構築可能ではないため、うまく機能しません。これはイテレータに必要です。ラムダに使用するラッパーは次のとおりです。

#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);
}

次に、これを行うことができます:

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;
}
于 2012-10-01T15:22:26.767 に答える
2

@ForEverの答え(#define BOOST_RESULT_OF_USE_DECLTYPE)は私にはうまくいきませんでした。そして、@ Paulの答えは長すぎます(そして一般的すぎます)。より具体的な解決策は次のとおりです。

#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;
}

(2016年、Boost 1.58ですが、これはまだ壊れています。少なくともキャプチャなしのラムダは、の要件を満たす必要がありboost::transformedます。)

ラムダにキャプチャがない場合(あなたの場合ではない)、コードは少し単純になるか、次のように使用できます。

...
int(*my_ftor)(int) = [](int r)->int{return ...;}; // function pointer default constructible and callable
cout<<*br::max_element(a|badpt::transformed(my_ftor))<<endl;
...
于 2016-05-10T08:45:44.940 に答える