1 /*=============================================================================
2 Copyright (c) 2017 Paul Fultz II
3 match.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/match.hpp>
8 #include <boost/hof/static.hpp>
9 #include <boost/hof/lambda.hpp>
10 #include <boost/hof/placeholders.hpp>
11 #include <boost/hof/limit.hpp>
12 #include "test.hpp"
13
14 #include <memory>
15
16 namespace test1
17 {
18 struct int_class
19 {
operator ()test1::int_class20 int operator()(int) const
21 {
22 return 1;
23 }
24 };
25
26 struct foo
27 {};
28
29 struct foo_class
30 {
operator ()test1::foo_class31 foo operator()(foo) const
32 {
33 return foo();
34 }
35 };
36
37 static constexpr boost::hof::static_<boost::hof::match_adaptor<int_class, foo_class> > fun = {};
38
39 static_assert(std::is_same<int, decltype(fun(1))>::value, "Failed match");
40 static_assert(std::is_same<foo, decltype(fun(foo()))>::value, "Failed match");
41 }
42
43 struct int_class
44 {
operator ()int_class45 constexpr int operator()(int) const
46 {
47 return 1;
48 }
49 };
50
51 struct foo
52 {};
53
54 struct foo_class
55 {
operator ()foo_class56 constexpr int operator()(foo) const
57 {
58 return 2;
59 }
60 };
61
62 static constexpr boost::hof::match_adaptor<int_class, foo_class> fun = {};
63
BOOST_HOF_TEST_CASE()64 BOOST_HOF_TEST_CASE()
65 {
66
67 BOOST_HOF_TEST_CHECK(fun(1) == 1);
68 BOOST_HOF_TEST_CHECK(fun(foo()) == 2);
69
70 BOOST_HOF_STATIC_TEST_CHECK(fun(1) == 1);
71 BOOST_HOF_STATIC_TEST_CHECK(fun(foo()) == 2);
72 };
73
BOOST_HOF_TEST_CASE()74 BOOST_HOF_TEST_CASE()
75 {
76
77 BOOST_HOF_TEST_CHECK(boost::hof::reveal(fun)(1) == 1);
78 BOOST_HOF_TEST_CHECK(boost::hof::reveal(fun)(foo()) == 2);
79
80 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::reveal(fun)(1) == 1);
81 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::reveal(fun)(foo()) == 2);
82 };
83
BOOST_HOF_TEST_CASE()84 BOOST_HOF_TEST_CASE()
85 {
86
87 constexpr auto lam = boost::hof::match(
88 BOOST_HOF_STATIC_LAMBDA(int) { return 1; },
89 BOOST_HOF_STATIC_LAMBDA(foo) { return 2; }
90 );
91
92 BOOST_HOF_TEST_CHECK(lam(1) == 1);
93 BOOST_HOF_TEST_CHECK(lam(foo()) == 2);
94 };
95
BOOST_HOF_TEST_CASE()96 BOOST_HOF_TEST_CASE()
97 {
98 int i = 0;
99 auto lam = boost::hof::match(
100 [&](int) { return i+1; },
101 [&](foo) { return i+2; }
102 );
103 // Disable this check on msvc, since lambdas might be default constructible
104 #ifndef _MSC_VER
105 STATIC_ASSERT_NOT_DEFAULT_CONSTRUCTIBLE(decltype(lam));
106 #endif
107 BOOST_HOF_TEST_CHECK(lam(1) == 1);
108 BOOST_HOF_TEST_CHECK(lam(foo()) == 2);
109 };
110
111
BOOST_HOF_TEST_CASE()112 BOOST_HOF_TEST_CASE()
113 {
114 struct not_default_constructible
115 {
116 int i;
117 not_default_constructible(int x) : i(x)
118 {}
119 };
120 STATIC_ASSERT_NOT_DEFAULT_CONSTRUCTIBLE(not_default_constructible);
121 not_default_constructible ndc = not_default_constructible(0);
122 auto lam = boost::hof::match(
123 [&](int) { return ndc.i+1; },
124 [&](foo) { return ndc.i+2; }
125 );
126 // Disable this check on msvc, since lambdas might be default constructible
127 #ifndef _MSC_VER
128 STATIC_ASSERT_NOT_DEFAULT_CONSTRUCTIBLE(decltype(lam));
129 #endif
130
131 BOOST_HOF_TEST_CHECK(lam(1) == 1);
132 BOOST_HOF_TEST_CHECK(lam(foo()) == 2);
133 };
134
135
136 struct int_move_class
137 {
138 std::unique_ptr<int> i;
int_move_classint_move_class139 int_move_class() : i(new int(1))
140 {}
operator ()int_move_class141 int operator()(int) const
142 {
143 return *i;
144 }
145 };
146
147 struct foo_move_class
148 {
149 std::unique_ptr<int> i;
foo_move_classfoo_move_class150 foo_move_class() : i(new int(2))
151 {}
operator ()foo_move_class152 int operator()(foo) const
153 {
154 return *i;
155 }
156 };
157
BOOST_HOF_TEST_CASE()158 BOOST_HOF_TEST_CASE()
159 {
160 auto fun_move = boost::hof::match(int_move_class(), foo_move_class());
161 BOOST_HOF_TEST_CHECK(fun_move(1) == 1);
162 BOOST_HOF_TEST_CHECK(fun_move(foo()) == 2);
163
164 };
165
BOOST_HOF_TEST_CASE()166 BOOST_HOF_TEST_CASE()
167 {
168 const auto negate = (!boost::hof::_);
169 const auto sub = (boost::hof::_ - boost::hof::_);
170 BOOST_HOF_TEST_CHECK(boost::hof::match(negate, sub)(0) == negate(0));
171 BOOST_HOF_TEST_CHECK(boost::hof::match(negate, sub)(0, 1) == sub(0, 1));
172 }
173
BOOST_HOF_TEST_CASE()174 BOOST_HOF_TEST_CASE()
175 {
176 const auto negate = (!boost::hof::_1);
177 const auto sub = (boost::hof::_1 - boost::hof::_2);
178 BOOST_HOF_TEST_CHECK(boost::hof::match(negate, sub)(0) == negate(0));
179 // This is test is disabled because its invalid. It is valid to give more
180 // parameters than what are used by the placeholders. So negate(0, 1) is a
181 // valid call, which makes the following test fail with ambigous overload.
182 // BOOST_HOF_TEST_CHECK(boost::hof::match(negate, sub)(0, 1) == sub(0, 1));
183 }
184
BOOST_HOF_TEST_CASE()185 BOOST_HOF_TEST_CASE()
186 {
187 const auto negate = boost::hof::limit_c<1>(!boost::hof::_1);
188 const auto sub = boost::hof::limit_c<2>(boost::hof::_1 - boost::hof::_2);
189 BOOST_HOF_TEST_CHECK(boost::hof::match(negate, sub)(0) == negate(0));
190 // This test will pass because we have limited the number of parameters.
191 BOOST_HOF_TEST_CHECK(boost::hof::match(negate, sub)(0, 1) == sub(0, 1));
192 }
193
194