1 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
2
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #include <boost/leaf/detail/config.hpp>
7 #include <boost/leaf/context.hpp>
8 #include <boost/leaf/pred.hpp>
9 #include <boost/leaf/handle_errors.hpp>
10 #include "_test_ec.hpp"
11
12 namespace leaf = boost::leaf;
13
14 template <class... T>
15 struct unwrap_tuple;
16
17 template <>
18 struct unwrap_tuple<std::tuple<>>
19 {
20 using type = std::tuple<>;
21 };
22
23 template <template <class> class S, class... E>
24 struct unwrap_tuple<std::tuple<S<E>...>>
25 {
26 using type = std::tuple<E...>;
27 };
28
29 template <class... H>
expd(H &&...)30 typename unwrap_tuple<typename std::decay<decltype(std::declval<typename leaf::context_type_from_handlers<H...>>().tup())>::type>::type * expd( H && ... )
31 {
32 return 0;
33 }
34
35 template <class T, class U>
test(U *)36 void test( U * )
37 {
38 static_assert(std::is_same<T,U>::value,"context deduction");
39 }
40
41 template <int> struct info { int value; };
42
43 enum class my_error_code
44 {
45 ok,
46 error1,
47 error2,
48 error3
49 };
50
51 namespace std
52 {
53 template <> struct is_error_code_enum<my_error_code>: std::true_type { };
54 }
55
56 enum class my_error_condition
57 {
58 ok,
59 cond1
60 };
61
62 namespace std
63 {
64 template <> struct is_error_condition_enum<my_error_condition>: std::true_type { };
65 }
66
not_called_on_purpose()67 void not_called_on_purpose()
68 {
69 test< std::tuple<> >( expd([]( leaf::error_info const & ){ }) );
70
71 test< std::tuple<info<1>> >( expd([]( info<1> ){ }) );
72 test< std::tuple<info<1>> >( expd([]( info<1> const ){ }) );
73 test< std::tuple<info<1>> >( expd([]( info<1> const & ){ }) );
74 test< std::tuple<info<1>> >( expd([]( info<1>, leaf::error_info const & ){ }) );
75
76 test< std::tuple<info<1>,info<2>> >( expd([]( info<1> ){ }, []( info<2> ){ }) );
77 test< std::tuple<info<1>,info<2>> >( expd([]( info<1> ){ }, []( info<1>, info<2> ){ }) );
78 test< std::tuple<info<1>,info<2>> >( expd([]( info<1>, info<2> ){ }, []( info<2> ){ }) );
79 test< std::tuple<info<1>,info<2>> >( expd([]( info<1>, info<2> ){ }, []( info<1>, info<2> ){ }) );
80
81 test< std::tuple<info<1>,info<2>> >( expd([]( leaf::error_info const &, info<1> ){ }, []( info<2> ){ }) );
82 test< std::tuple<info<1>,info<2>> >( expd([]( leaf::error_info const &, info<1> ){ }, []( info<1>, info<2> ){ }) );
83 test< std::tuple<info<1>,info<2>> >( expd([]( leaf::error_info const &, info<1>, info<2> ){ }, []( info<2> ){ }) );
84 test< std::tuple<info<1>,info<2>> >( expd([]( leaf::error_info const &, info<1>, info<2> ){ }, []( info<1>, info<2> ){ }) );
85
86 test< std::tuple<info<1>,info<2>> >( expd([]( info<1>, leaf::error_info const & ){ }, []( info<2> ){ }) );
87 test< std::tuple<info<1>,info<2>> >( expd([]( info<1>, leaf::error_info const & ){ }, []( info<1>, info<2> ){ }) );
88 test< std::tuple<info<1>,info<2>> >( expd([]( info<1>, leaf::error_info const &, info<2> ){ }, []( info<2> ){ }) );
89 test< std::tuple<info<1>,info<2>> >( expd([]( info<1>, leaf::error_info const &, info<2> ){ }, []( info<1>, info<2> ){ }) );
90
91 test< std::tuple<info<1>,info<2>> >( expd([]( info<1> ){ }, []( leaf::error_info const &, info<2> ){ }) );
92 test< std::tuple<info<1>,info<2>> >( expd([]( info<1> ){ }, []( leaf::error_info const &, info<1>, info<2> ){ }) );
93 test< std::tuple<info<1>,info<2>> >( expd([]( info<1>, info<2> ){ }, []( leaf::error_info const &, info<2> ){ }) );
94 test< std::tuple<info<1>,info<2>> >( expd([]( info<1>, info<2> ){ }, []( leaf::error_info const &, info<1>, info<2> ){ }) );
95
96 test< std::tuple<info<1>,info<2>> >( expd([]( info<1> ){ }, []( info<2>, leaf::error_info const & ){ }) );
97 test< std::tuple<info<1>,info<2>> >( expd([]( info<1> ){ }, []( info<1>, leaf::error_info const &, info<2> ){ }) );
98 test< std::tuple<info<1>,info<2>> >( expd([]( info<1>, info<2> ){ }, []( info<2>, leaf::error_info const & ){ }) );
99 test< std::tuple<info<1>,info<2>> >( expd([]( info<1>, info<2> ){ }, []( info<1>, leaf::error_info const &, info<2> ){ }) );
100
101 test< std::tuple<info<1>,info<2>,info<3>> >( expd([]( info<1> ){ }, []( info<2> ){ }, []( info<3> ){ }) );
102 test< std::tuple<info<1>,info<2>,info<3>> >( expd([]( info<1> ){ }, []( info<1>, info<2> ){ }, []( info<1>, info<3> ){ }) );
103 test< std::tuple<info<1>,info<2>,info<3>> >( expd([]( info<1> ){ }, []( info<1>, info<2> ){ }, []( info<1>, info<3> ){ }) );
104 test< std::tuple<info<1>,info<2>,info<3>> >( expd([]( info<1>, info<2> ){ }, []( info<2> ){ }, []( info<3> ){ }) );
105 test< std::tuple<info<1>,info<2>,info<3>> >( expd([]( info<1>, info<2> ){ }, []( info<2> ){ }, []( info<3> ){ }) );
106 test< std::tuple<info<1>,info<2>,info<3>> >( expd([]( info<1> ){ }, []( info<2> ){ }, []( info<3>, info<2> ){ }) );
107 test< std::tuple<info<1>,info<2>,info<3>> >( expd([]( info<1> ){ }, []( info<2> ){ }, []( info<3>, info<2> ){ }) );
108 test< std::tuple<info<1>,info<3>,info<2>> >( expd([]( info<1>, info<3> ){ }, []( info<2> ){ }, []( info<3> ){ }) );
109 test< std::tuple<info<1>,info<3>,info<2>> >( expd([]( info<1>, info<3> ){ }, []( info<2> ){ }, []( info<3> ){ }) );
110 test< std::tuple<info<1>,info<2>,info<3>> >( expd([]( info<1> ){ }, []( info<2>, info<3> ){ }, []( info<3> ){ }) );
111 test< std::tuple<info<1>,info<2>,info<3>> >( expd([]( info<1> ){ }, []( info<2>, info<3> ){ }, []( info<3> ){ }) );
112
113 test< std::tuple<my_error_code> >( expd([]( leaf::match<my_error_code, my_error_code::error1> ){ }) );
114 test< std::tuple<std::error_code> >( expd([]( leaf::match<leaf::condition<cond_x>, cond_x::x00> ){ }) );
115
116 test< std::tuple<info<1>> >( expd([]( leaf::match_value<info<1>,42> ){ }) );
117
118 test< std::tuple<std::error_code> >( expd([]( leaf::match<leaf::condition<my_error_condition>, my_error_condition::cond1> ){ }) );
119 #if __cplusplus >= 201703L
120 test< std::tuple<std::error_code> >( expd([]( leaf::match<std::error_code, my_error_code::error1> ){ }) );
121 test< std::tuple<std::error_code> >( expd([]( leaf::match<std::error_code, my_error_condition::cond1> ){ }) );
122 #endif
123
124 #ifndef BOOST_LEAF_NO_EXCEPTIONS
125 test< std::tuple<info<1>> >( expd([]( leaf::catch_<std::exception>, info<1> ){ }) );
126 #endif
127
128 test< std::tuple<info<1>,info<2>,info<3>> >( expd([]( info<1> const *, info<2> ){ }, []( info<1>, info<3> const * ){ }) );
129 test< std::tuple<info<1>,info<2>,info<3>> >( expd([]( info<1> const, info<2> ){ }, []( info<1> const *, info<3> ){ }) );
130
131 #if BOOST_LEAF_DIAGNOSTICS
132 test< std::tuple<info<1>,info<2>,leaf::leaf_detail::e_unexpected_count> >( expd([]( info<1>, info<2>, leaf::diagnostic_info const & ){ }, []( info<1>, info<2> ){ }) );
133 test< std::tuple<info<1>,info<2>,leaf::leaf_detail::e_unexpected_info> >( expd([]( info<1>, info<2> ){ }, []( info<1>, leaf::verbose_diagnostic_info const &, info<2> ){ }) );
134 test< std::tuple<info<1>,info<2>,leaf::leaf_detail::e_unexpected_count,leaf::leaf_detail::e_unexpected_info> >( expd([]( info<1>, info<2>, leaf::diagnostic_info const & ){ }, []( info<1>, leaf::verbose_diagnostic_info const &, info<2> ){ }) );
135 #else
136 test< std::tuple<info<1>,info<2>> >( expd([]( info<1>, info<2>, leaf::diagnostic_info const & ){ }, []( info<1>, info<2> ){ }) );
137 test< std::tuple<info<1>,info<2>> >( expd([]( info<1>, info<2> ){ }, []( info<1>, leaf::verbose_diagnostic_info const &, info<2> ){ }) );
138 test< std::tuple<info<1>,info<2>> >( expd([]( info<1>, info<2>, leaf::diagnostic_info const & ){ }, []( info<1>, leaf::verbose_diagnostic_info const &, info<2> ){ }) );
139 #endif
140
141 {
142 auto error_handlers = std::make_tuple(
143 []( info<2> ) { },
144 []( info<3> ) { } );
145 test< std::tuple<info<1>, info<2>, info<3>, info<4>, info<5>>>( expd(
146 []( info<1> ) { },
147 error_handlers,
148 []( info<4>, info<5> ) { } ) );
149 }
150
151 {
152 auto error_handlers1 = std::make_tuple(
153 []( info<4> ) { },
154 []( info<5> ) { } );
155 auto error_handlers2 = std::make_tuple(
156 []( info<2> ) { },
157 []( info<3> ) { },
158 error_handlers1 );
159 test< std::tuple<info<1>, info<2>, info<3>, info<4>, info<5>, info<6>>>( expd(
160 []( info<1> ) { },
161 error_handlers2,
162 []( info<4>, info<5> ) { },
163 []( info<6> ) { } ) );
164 }
165 }
166
main()167 int main()
168 {
169 return 0;
170 }
171