Boost.Phoenix で、ユーザ側で定義した関数を呼び出すためのアダプタ

boost::phoenix::function を使用して定義することも出来ますが、Boost.Phoenix に用意されているアダプタを使用すればもっと簡単に定義することが出来ます。

BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY

引数のない関数をアダプトします。

namespace demo{

    int
    nullary_func(){
        return 42;
    }

}  // namespace demo

// 引数なしの関数を定義
BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(
    int,                 // 戻り値型
    nullary_func,        // 定義する関数名
    demo::nullary_func   // 呼び出す関数名
)

assert((arg1 + nullary_func())(1) == 44);

BOOST_PHOENIX_ADAPT_FUNCTION

引数がある関数をアダプトします。

namespace demo{

    int
    plus(int a, int b){
    return a + b;
    }

    template<typename T>
    T
    plus(T a, T b, T c){
    return a + b + c;
    }

}  // namespace demo

// 引数ありの関数を定義
BOOST_PHOENIX_ADAPT_FUNCTION(
    int,                // 戻り値型
    plus,               // 定義する関数名
    demo::plus,         // 呼び出す関数名
    2                   // 引数の数
)

// 引数型によって、戻り値型が変わる場合
BOOST_PHOENIX_ADAPT_FUNCTION(
    // A0 .. An が、引数型として使用出来る
    typename boost::remove_reference<A0>::type,
    plus,
    demo::plus,
    3
)

assert(plus(arg1, arg2)(5, 2) == 7);
assert(plus(arg1, arg2, 3)(5, 2) == 10);

BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY

引数がない関数オブジェクトをアダプトします。

namespace demo{

    struct nullary_callable{
        typedef int result_type;
        result_type
        operator ()() const{
            return 42;
        }
    };

}  // namespace demo

// 引数なしの関数オブジェクトを定義
BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY(
    nullary_callable,            // 定義する関数名
    demo::nullary_callable       // 呼び出す関数名
)

assert((arg1 + nullary_callable())() == 42);

BOOST_PHOENIX_ADAPT_CALLABLE

引数がある関数オブジェクトをアダプトします。

namespace demo{

    struct minus{
        template<typename Sig>
        struct result;
        
        template<typename This, typename A0, typename A1>
        struct result<This(A0, A1)>
            : boost::remove_reference<A0>{};

        template<typename This, typename A0, typename A1, typename A2>
        struct result<This(A0, A1, A2)>
            : boost::remove_reference<A0>{};
            
        template<typename A0,  typename A1>
        typename result<minus(A0, A1)>::type
        operator ()(A0 const& a0, A1 const& a1) const{
            return a0 - a1;
        }

        template<typename A0,  typename A1, typename A2>
        typename result<minus(A0, A1, A2)>::type
        operator ()(A0 const& a0, A1 const& a1, A2 const& a2) const{
            return a0 - a1 - a2;
        }
    };

}  // namespace demo

// 引数ありの関数オブジェクトを定義
BOOST_PHOENIX_ADAPT_CALLABLE(
    minus,                      // 定義する関数名
    demo::minus,                // 呼び出す関数名
    2                           // 引数の数
)
BOOST_PHOENIX_ADAPT_CALLABLE(
    minus,
    demo::minus,
    3
)

assert(minus(arg1, arg2)(5, 2) == 3);
assert(minus(arg1, arg2, 3)(5, 2) == 0);

[ソース]

#include <boost/phoenix/function/adapt_function.hpp>
#include <boost/phoenix/function/adapt_callable.hpp>
#include <boost/phoenix/core/argument.hpp>
#include <boost/phoenix/operator.hpp>

namespace demo{

int
nullary_func(){
    return 42;
}

int
plus(int a, int b){
    return a + b;
}

template<typename T>
T
plus(T a, T b, T c){
    return a + b + c;
}

struct nullary_callable{
    typedef int result_type;
    result_type
    operator ()() const{
        return 42;
    }
};

struct minus{
    template<typename Sig>
    struct result;
    
    template<typename This, typename A0, typename A1>
    struct result<This(A0, A1)>
        : boost::remove_reference<A0>{};

    template<typename This, typename A0, typename A1, typename A2>
    struct result<This(A0, A1, A2)>
        : boost::remove_reference<A0>{};
        
    template<typename A0,  typename A1>
    typename result<minus(A0, A1)>::type
    operator ()(A0 const& a0, A1 const& a1) const{
        return a0 - a1;
    }

    template<typename A0,  typename A1, typename A2>
    typename result<minus(A0, A1, A2)>::type
    operator ()(A0 const& a0, A1 const& a1, A2 const& a2) const{
        return a0 - a1 - a2;
    }

};

}  // namespac demo

// 引数なしの関数を定義
BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(
    int,                 // 戻り値型
    nullary_func,        // 定義する関数名
    demo::nullary_func   // 呼び出す関数名
)

// 引数ありの関数を定義
BOOST_PHOENIX_ADAPT_FUNCTION(
    int,                // 戻り値型
    plus,               // 定義する関数名
    demo::plus,         // 呼び出す関数名
    2                   // 引数の数
)

// 引数型によって、戻り値型が変わる場合
BOOST_PHOENIX_ADAPT_FUNCTION(
    // A0 .. An が、引数型として使用出来る
    typename boost::remove_reference<A0>::type,
    plus,
    demo::plus,
    3
)

// 引数なしの関数オブジェクトを定義
BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY(
    nullary_callable,            // 定義する関数名
    demo::nullary_callable       // 呼び出す関数名
)

// 引数ありの関数オブジェクトを定義
BOOST_PHOENIX_ADAPT_CALLABLE(
    minus,                      // 定義する関数名
    demo::minus,                // 呼び出す関数名
    2                           // 引数の数
)
BOOST_PHOENIX_ADAPT_CALLABLE(
    minus,
    demo::minus,
    3
)

#include <iostream>

int
main(){
    namespace phx = boost::phoenix;
    using phx::arg_names::arg1;
    using phx::arg_names::arg2;
    using phx::arg_names::arg3;
    
    (std::cout << arg1 << ":" << nullary_func() << std::endl)(10);
    (std::cout << plus(arg1, arg2) << std::endl )(3, 2);
    (std::cout << plus(arg1, arg2, arg3) << std::endl )(0.52f, 2.24f, -1.44f);
    (std::cout << arg1 + nullary_callable() << std::endl)(20);
    (std::cout << minus(arg1, arg2) << std::endl )(3, 2);
    (std::cout << minus(arg1, arg2, 1) << std::endl )(3, 2);

    return 0;
}

[出力]

10:42
5
1.32
62
1
0

[boost]

  • ver 1.47.0