1 /*=============================================================================
2 Copyright (c) 2001-2007 Joel de Guzman
3 Copyright (c) 2015 John Fletcher
4
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #include <iostream>
9 #include <cmath>
10 #include <boost/detail/lightweight_test.hpp>
11 #include <boost/phoenix/core.hpp>
12 #include <boost/phoenix/operator.hpp>
13 #include <boost/phoenix/bind.hpp>
14
15 namespace phoenix = boost::phoenix;
16 using std::cout;
17 using std::pow;
18
19 struct test
20 {
21 typedef void result_type;
22
23 void
operator ()test24 operator()() const
25 {
26 cout << "Test lazy functions...\n";
27 }
28 };
29
30 struct sqr
31 {
32 template <typename Sig>
33 struct result;
34
35 template <typename This, typename Arg>
36 struct result<This(Arg&)>
37 {
38 typedef Arg type;
39 };
40
41 template <typename Arg>
42 Arg
operator ()sqr43 operator()(Arg n) const
44 {
45 return n * n;
46 }
47 };
48
49 struct fact
50 {
51 template <typename Sig>
52 struct result;
53
54 template <typename This, typename Arg>
55 struct result<This(Arg&)>
56 {
57 typedef Arg type;
58 };
59
60 template <typename Arg>
61 Arg
operator ()fact62 operator()(Arg n) const
63 {
64 return (n <= 0) ? 1 : n * (*this)(n-1);
65 }
66 };
67
68 struct power
69 {
70 template<typename Sig>
71 struct result;
72
73 template<typename This, typename Arg1, typename Arg2>
74 struct result<This(Arg1&, Arg2&)>
75 {
76 typedef Arg1 type;
77 };
78
79 template <typename Arg1, typename Arg2>
80 Arg1
operator ()power81 operator()(Arg1 a, Arg2 b) const
82 {
83 return pow(a, b);
84 }
85 };
86
87 struct add
88 {
89 template <typename Sig>
90 struct result;
91
92 template <typename This, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
93 struct result<This(Arg1&, Arg2&, Arg3&, Arg4&)>
94 {
95 typedef Arg1 type;
96 };
97
98 template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
99 Arg1
operator ()add100 operator()(Arg1 a, Arg2 b, Arg3 c, Arg4 d) const
101 {
102 return a + b + c + d;
103 }
104 };
105
106 int
main()107 main()
108 {
109 using phoenix::bind;
110 using phoenix::ref;
111 using phoenix::arg_names::_1;
112 using phoenix::arg_names::arg1;
113 using phoenix::arg_names::arg2;
114
115 int i5 = 5;
116 double d5 = 5, d3 = 3;
117
118 test()();
119 BOOST_TEST(bind(sqr(), arg1)(i5) == (i5*i5));
120 BOOST_TEST(bind(fact(), 4)() == 24);
121 BOOST_TEST(bind(fact(), arg1)(i5) == 120);
122 BOOST_TEST((int)bind(power(), arg1, arg2)(d5, d3) == (int)std::pow(d5, d3));
123 BOOST_TEST((bind(sqr(), arg1) + 5)(i5) == ((i5*i5)+5));
124 BOOST_TEST(bind(add(), arg1, arg1, arg1, arg1)(i5) == (5+5+5+5));
125
126 int const ic5 = 5;
127 // testing consts
128 BOOST_TEST(bind(sqr(), arg1)(ic5) == (ic5*ic5));
129
130 // From Steven Watanabe
131 sqr s;
132 int x = 2;
133 int result = bind(ref(s), _1)(x);
134 BOOST_TEST(result == 4);
135
136 return boost::report_errors();
137 }
138