4

1つは呼び出し可能オブジェクト用、もう1つは関数引数用の2つのプレースホルダーを使用してラムダ式を記述し、呼び出し可能オブジェクトを指定すると最初に単項関数が返されるようにするにはどうすればよいですか。

以下の例でgenerateは、呼び出し可能オブジェクト自体の最初のプレースホルダーと引数の2番目のプレースホルダーを持つラムダ式である必要があります。呼び出しgenerate(c)は、関数呼び出し引数のみが欠落している単項関数を返す必要があります。実際、bool静的アサートによって証明されるように、それは何らかの形ですでに型を返します。

#include <boost/lambda/bind.hpp>

struct Arg {
};

struct Callable : std::unary_function<Arg, bool> {
    bool operator()( Arg const& a ) const { return true; }
};

int main( int argc, const char* argv[] ) {
    BOOST_AUTO(generate, boost::lambda::bind(boost::lambda::_1, boost::lambda::protect(boost::lambda::_1)));

    Callable c;
    BOOST_AUTO(fn, generate(c));

    BOOST_STATIC_ASSERT((boost::is_same<BOOST_TYPEOF(fn), bool>::value));
    Arg a;
    bool b = fn(a);
    _ASSERT(b==true);
}
4

3 に答える 3

4

Boost.Phoenixを使用している場合、答えは少し簡単でした。

#include <boost/phoenix/phoenix.hpp>

struct callable
{
    typedef bool result_type;

    bool operator()(int) const
    {
        return true;
    }
};

int main()
{
    using phx::bind;
    using phx::lambda;
    using phx::arg_names::_1;
    using phx::local_names::_a;

    auto generate = lambda(_a = _1)[bind(_a, _1)];
    auto fn = generate(callable());

    bool b = fn(8);
}

このソリューションは、OTによって投稿されたバージョンよりもはるかに一般的であるというわけではありません。引数や戻り値に関係なく、任意の単項関数オブジェクトで使用できます。

欠点は、現在のブーストトランクを使用する必要があります...

于 2011-03-10T20:35:08.193 に答える
1

思っていたほどエレガントではありませんが、私は自分の問題を解決しました。

   struct FCreateBind {
        typedef boost::_bi::bind_t<bool, Callable, boost::_bi::list2<boost::arg<1>, boost::arg<2> >  > result_type;
        result_type operator()( Callable const& c ) const {
            return boost::bind<bool>(c, _1);
        }
};
BOOST_AUTO(generate, boost::bind(FCreateBind(), _1));

   BOOST_AUTO(fn, generate(Callable());
   bool b = fn(Arg());

もちろん、この単純な例では、それ自体が呼び出し可能なオブジェクトであるBOOST_AUTO(generate, boost::lambda_1)ため、私はただ書くことができます。しかし、生成された関数がnullary関数になるように、事前Callableにの引数を設定する方法を探していました。このソリューションでは、これを内部で実行できます。CallablefnFCreateBind

FCreateBindおそらく同様に排除することができますが、オーバーロードされたグローバル関数へのポインターを定義する方法をまだ理解していませんboost::bind

于 2011-03-10T10:08:19.660 に答える
0

Though I'm not 100% sure I understand the question, the following code might meet your purpose:

template< class R >
struct FCreateBind {
  typedef boost::function< R() > result_type;

  template< class T, class U >
  result_type operator()( T const& x, U const& y ) const {
    return boost::bind( x, y );
  }
};

int main() {
  BOOST_AUTO( generate, boost::bind( FCreateBind< bool >(), Callable(), _1 ) );
  BOOST_AUTO( fn, generate( Arg() ) );
  bool b = fn();
}

That being said, probably this isn't as pretty as the questioner expects...
As you mentioned, if we specify one of the overloads of boost::bind explicitly, FCreateBind wouldn't be needed. However, as far as I saw, there seems not to be the portable way to specify the overload. So, in this case, probably we have to depend on the internal of boost.
For your information, the following code could be compiled when I tested:

int main() {
  namespace bb = boost::_bi; // Sorry, for brevity
  bb::bind_t< bb::unspecified, Callable, bb::list1< bb::value< Arg > > >
    (*bi)( Callable, Arg ) = boost::bind< bb::unspecified, Callable, Arg >;
  BOOST_AUTO( generate, boost::bind( bi, Callable(), _1 ) );
  BOOST_AUTO( fn, generate( Arg() ) );
  bool b = fn();
}

Hope this helps

于 2011-03-10T22:59:32.593 に答える