1 /*=============================================================================
2 Copyright (c) 2017 Paul Fultz II
3 first_of.cpp
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7 #include <boost/hof/first_of.hpp>
8 #include <boost/hof/static.hpp>
9 #include <boost/hof/lambda.hpp>
10 #include <boost/hof/function.hpp>
11 #include <memory>
12 #include "test.hpp"
13
14 namespace conditional_test {
15
16 #define CONDITIONAL_FUNCTION(n) \
17 struct t ## n {}; \
18 struct f ## n \
19 { \
20 constexpr int operator()(t ## n) const \
21 { \
22 return n; \
23 } \
24 };
25
26 CONDITIONAL_FUNCTION(1)
27 CONDITIONAL_FUNCTION(2)
28 CONDITIONAL_FUNCTION(3)
29
30 #define CONDITIONAL_MOVE_FUNCTION(n) \
31 struct t_move ## n {}; \
32 struct f_move ## n \
33 { \
34 std::unique_ptr<int> i;\
35 f_move ## n(int ip) : i(new int(ip)) {}; \
36 int operator()(t_move ## n) const \
37 { \
38 return *i; \
39 } \
40 };
41
42 CONDITIONAL_MOVE_FUNCTION(1)
43 CONDITIONAL_MOVE_FUNCTION(2)
44 CONDITIONAL_MOVE_FUNCTION(3)
45
46 struct ff
47 {
operator ()conditional_test::ff48 constexpr int operator()(t2) const
49 {
50 return 500;
51 }
52 };
53
54 static constexpr boost::hof::static_<boost::hof::first_of_adaptor<f1, f2, f3, ff> > f = {};
55
56 BOOST_HOF_STATIC_FUNCTION(f_constexpr) = boost::hof::first_of_adaptor<f1, f2, f3, ff>();
57
BOOST_HOF_TEST_CASE()58 BOOST_HOF_TEST_CASE()
59 {
60 BOOST_HOF_TEST_CHECK(f(t1()) == 1);
61 BOOST_HOF_TEST_CHECK(f(t2()) == 2);
62 BOOST_HOF_TEST_CHECK(f(t3()) == 3);
63
64 BOOST_HOF_STATIC_TEST_CHECK(f_constexpr(t1()) == 1);
65 BOOST_HOF_STATIC_TEST_CHECK(f_constexpr(t2()) == 2);
66 BOOST_HOF_STATIC_TEST_CHECK(f_constexpr(t3()) == 3);
67 }
68
BOOST_HOF_TEST_CASE()69 BOOST_HOF_TEST_CASE()
70 {
71 BOOST_HOF_TEST_CHECK(boost::hof::first_of(f1{}, f2{})(t1()) == 1);
72 BOOST_HOF_TEST_CHECK(boost::hof::first_of(f1{}, f2{})(t2()) == 2);
73
74 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(f1{}, f2{})(t1()) == 1);
75 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(f1{}, f2{})(t2()) == 2);
76 }
77
78 #if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7)
79 #else
80
BOOST_HOF_TEST_CASE()81 BOOST_HOF_TEST_CASE()
82 {
83 BOOST_HOF_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f1{}, f2{}))(t1()) == 1);
84 BOOST_HOF_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f1{}, f2{}))(t2()) == 2);
85
86 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f1{}, f2{}))(t1()) == 1);
87 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f1{}, f2{}))(t2()) == 2);
88 }
89
BOOST_HOF_TEST_CASE()90 BOOST_HOF_TEST_CASE()
91 {
92 BOOST_HOF_TEST_CHECK(boost::hof::first_of(f1{}, boost::hof::first_of(f2{}, f3{}))(t1()) == 1);
93 BOOST_HOF_TEST_CHECK(boost::hof::first_of(f1{}, boost::hof::first_of(f2{}, f3{}))(t2()) == 2);
94 BOOST_HOF_TEST_CHECK(boost::hof::first_of(f1{}, boost::hof::first_of(f2{}, f3{}))(t3()) == 3);
95
96 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(f1{}, boost::hof::first_of(f2{}, f3{}))(t1()) == 1);
97 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(f1{}, boost::hof::first_of(f2{}, f3{}))(t2()) == 2);
98 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(f1{}, boost::hof::first_of(f2{}, f3{}))(t3()) == 3);
99 }
100
BOOST_HOF_TEST_CASE()101 BOOST_HOF_TEST_CASE()
102 {
103 BOOST_HOF_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f2{}, f3{}))(t1()) == 1);
104 BOOST_HOF_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f2{}, f3{}))(t2()) == 2);
105 BOOST_HOF_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f2{}, f3{}))(t3()) == 3);
106
107 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f2{}, f3{}))(t1()) == 1);
108 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f2{}, f3{}))(t2()) == 2);
109 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f2{}, f3{}))(t3()) == 3);
110 }
111
112 #endif
113
BOOST_HOF_TEST_CASE()114 BOOST_HOF_TEST_CASE()
115 {
116 auto f_move_local = boost::hof::first_of(f_move1(1), f_move2(2), f_move3(3));
117 STATIC_ASSERT_MOVE_ONLY(decltype(f_move_local));
118 BOOST_HOF_TEST_CHECK(f_move_local(t_move1()) == 1);
119 BOOST_HOF_TEST_CHECK(f_move_local(t_move2()) == 2);
120 BOOST_HOF_TEST_CHECK(f_move_local(t_move3()) == 3);
121 }
122 #ifndef _MSC_VER
123 static constexpr auto lam = boost::hof::first_of(
124 BOOST_HOF_STATIC_LAMBDA(t1)
125 {
126 return 1;
127 },
128 BOOST_HOF_STATIC_LAMBDA(t2)
129 {
130 return 2;
131 },
132 BOOST_HOF_STATIC_LAMBDA(t3)
133 {
134 return 3;
135 }
136 );
137
BOOST_HOF_TEST_CASE()138 BOOST_HOF_TEST_CASE()
139 {
140 BOOST_HOF_TEST_CHECK(lam(t1()) == 1);
141 BOOST_HOF_TEST_CHECK(lam(t2()) == 2);
142 BOOST_HOF_TEST_CHECK(lam(t3()) == 3);
143 }
144 #endif
145
146 BOOST_HOF_STATIC_LAMBDA_FUNCTION(static_fun) = boost::hof::first_of(
147 [](t1)
__anon19aeceda0102(t1) 148 {
149 return 1;
150 },
151 [](t2)
__anon19aeceda0202(t2) 152 {
153 return 2;
154 },
155 [](t3)
__anon19aeceda0302(t3) 156 {
157 return 3;
158 }
159 );
160
BOOST_HOF_TEST_CASE()161 BOOST_HOF_TEST_CASE()
162 {
163 BOOST_HOF_TEST_CHECK(static_fun(t1()) == 1);
164 BOOST_HOF_TEST_CHECK(static_fun(t2()) == 2);
165 BOOST_HOF_TEST_CHECK(static_fun(t3()) == 3);
166 }
167
BOOST_HOF_TEST_CASE()168 BOOST_HOF_TEST_CASE()
169 {
170 BOOST_HOF_TEST_CHECK(boost::hof::first_of(boost::hof::identity, boost::hof::identity)(3) == 3);
171 }
172
173 template<class T>
174 struct throw_fo
175 {
operator ()conditional_test::throw_fo176 void operator()(T) const {}
177 };
178
179 template<class T>
180 struct no_throw_fo
181 {
operator ()conditional_test::no_throw_fo182 void operator()(T) const noexcept {}
183 };
184 #if BOOST_HOF_HAS_NOEXCEPT_DEDUCTION
BOOST_HOF_TEST_CASE()185 BOOST_HOF_TEST_CASE()
186 {
187 typedef boost::hof::first_of_adaptor<throw_fo<t1>, no_throw_fo<t2>> fun;
188 auto g = fun{};
189 static_assert(noexcept(g(t2{})), "noexcept conditional");
190 static_assert(!noexcept(g(t1{})), "noexcept conditional");
191
192 static_assert(noexcept(fun{}(t2{})), "noexcept conditional");
193 static_assert(!noexcept(fun{}(t1{})), "noexcept conditional");
194 }
195
BOOST_HOF_TEST_CASE()196 BOOST_HOF_TEST_CASE()
197 {
198 typedef boost::hof::first_of_adaptor<no_throw_fo<t2>, throw_fo<t1>> fun;
199 auto g = fun{};
200 static_assert(noexcept(g(t2{})), "noexcept conditional");
201 static_assert(!noexcept(g(t1{})), "noexcept conditional");
202
203 static_assert(noexcept(fun{}(t2{})), "noexcept conditional");
204 static_assert(!noexcept(fun{}(t1{})), "noexcept conditional");
205 }
206
BOOST_HOF_TEST_CASE()207 BOOST_HOF_TEST_CASE()
208 {
209 static_assert(noexcept(boost::hof::first_of_adaptor<no_throw_fo<t2>, throw_fo<t1>>{}(t2{})), "noexcept conditional");
210 static_assert(!noexcept(boost::hof::first_of_adaptor<no_throw_fo<t2>, throw_fo<t1>>{}(t1{})), "noexcept conditional");
211
212 static_assert(noexcept(boost::hof::first_of(no_throw_fo<t2>{}, throw_fo<t1>{})(t2{})), "noexcept conditional");
213 static_assert(!noexcept(boost::hof::first_of(no_throw_fo<t2>{}, throw_fo<t1>{})(t1{})), "noexcept conditional");
214 }
215 #endif
216 }
217