boost phoenix

In functional programming, functions are objects and can be processed like objects. With Boost.Phoenix, it is possible for a function to return another function as a result. It is also possible to pass a function as a parameter to another function. Because functions are objects, it's possible to distinguish between instantiation and execution. Accessing a function isn't equal to executing it.

Boost.Phoenix supports functional programming with function objects: Functions are objects based on classes which overload the operator(). That way function objects behave like other objects in c++. For example, they can be copied and stored in a container. However, they also behave like functions because they can be called.

1. phoenix

#include <boost/phoenix/phoenix.hpp>
#include <vector>
#include <algorithm>
#include <iostream>

bool is_odd(int i) { return i % 2 == 1; }

int main()
{
  std::vector<int> v{1, 2, 3, 4, 5};

  std::cout << std::count_if(v.begin(), v.end(), is_odd) << std::endl;

  auto lambda = [](int i){ return i % 2 == 1; };
  std::cout << std::count_if(v.begin(), v.end(), lambda) << std::endl;

  using namespace boost::phoenix::placeholders;
  auto phoenix = arg1 % 2 == 1;
  std::cout << std::count_if(v.begin(), v.end(), phoenix) << std::endl;

  std::vector<long> v2;
  v2.insert(v2.begin(), v.begin(), v.end()); auto phoenix = arg1 % 2 == 1; std::cout << std::count_if(v.begin(), v.end(), phoenix) << '\n'; std::cout << std::count_if(v2.begin(), v2.end(), phoenix) << '\n';
return 0; }

The Phoenix function differs from free-standing and lambda functions because it has no frame. While the other two functions have a function header with a signature, the Phoenix function seems to consist of a function body only. The crucial component of the Phoenix function is boost::phoenix::placeholders::arg1. arg1 is a global instance of a function object.

arg1 is used to define an unary function. The expression arg1 % 2 == 1 creates a new function that expects one parameter. The function isn’t executed immediately but stored in phoenix. phoenix is passed to std::count_if() which calls the predicate for every number in v.

Phoenix function parameters have no types. The lambda function lambda expects a parameter of type int. The Phoenix function phoenix will accept any type that the modulo operator can handle. Think of Phoenix functions as function templates. Like function templates, Phoenix functions can accept any type.

You can think of Phoenix functions as C++ code that isn’t executed immediately. The Phoenix function in example above looks like a condition that uses multiple logical and arithmetic operators. However, the condition isn’t executed immediately. It is only executed when it is accessed from within std::count_if(). The access in std::count_if() is a normal function call.

2. boost::phoenix::val()

#include <boost/phoenix/phoenix.hpp>
#include <vector>
#include <algorithm>
#include <iostream>

int main()
{
  std::vector<int> v{1, 2, 3, 4, 5};

  using namespace boost::phoenix;
  using namespace boost::phoenix::placeholders;
  auto phoenix = arg1 > val(2) && arg1 % val(2) == val(1);
  std::cout << std::count_if(v.begin(), v.end(), phoenix) << std::endl;
std::cout << arg1(1, 2, 3, 4, 5) << std::endl; auto v = boost::phoenix::val(2); std::cout << v() << std::endl;
return 0; }

boost::phoenix::val() returns a function object initialized with the values passed to boost::phoenix::val(). The acutal type of the function object dosen't matter.

arg1 is an instance of a function object. It can be used directly and called like a function. You can pass as many parameters as you like - arg1 returns the first one.

val() is a function to create an instance of a function object. The function object is initialized with the value passed as a parameter. Is the instance is accessed like a function, the value is returned.

3. create your own phoenix functions

#include <boost/phoenix/phoenix.hpp>
#include <vector>
#include <algorithm>
#include <iostream>

struct is_odd_impl
{
    typedef bool result_type;

    template <typename T>
    bool operator()(T t) const { return t % 2 == 1; }
};

boost::phoenix::function<is_odd_impl> is_odd;

int main()
{
  std::vector<int> v{1, 2, 3, 4, 5};

  using namespace boost::phoenix::placeholders;
  std::cout << std::count_if(v.begin(), v.end(), is_odd(arg1)) << std::endl;
  return 0;
}

Class should overload the operator operator(): when an odd number is passed in, the operator returns true. Please note that you must define the type result_type. Boost.Phoenix uses it to detect the type of the return value of the operator operator().

4. transform

#include <boost/phoenix/phoenix.hpp>
#include <vector>
#include <algorithm>
#include <iostream>

bool is_odd_function(int i) { return i % 2 == 1; }

BOOST_PHOENIX_ADAPT_FUNCTION(bool, is_odd, is_odd_function, 1)

bool is_odd(int i) {
return i % 2 == 1;
}
int main() { std::vector<int> v{1, 2, 3, 4, 5};
using namespace boost::phoenix;
using namespace boost::phoenix::placeholders; std::cout << std::count_if(v.begin(), v.end(), is_odd(arg1)) << std::endl;
 std::cout << std::count_if(v.begin(), v.end(), bind(is_odd, arg1)) << std::endl;
return 0; }

Use the macro BOOST_PHOENIX_ADAPT_FUNCTION to turn a free-standing function into a Phoenix function. Pass the type of the return value, the name of the Phoenix function to define, the name of the free-standing function, and the number of parameters to the macro.

转载于:https://www.cnblogs.com/sssblog/p/11309671.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值