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