• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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