1 
2 //  (C) Copyright Edward Diener 2019
3 //  Use, modification and distribution are subject to the Boost Software License,
4 //  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 //  http://www.boost.org/LICENSE_1_0.txt).
6 
7 #if !defined(BOOST_TTI_DETAIL_UNION_HPP)
8 #define BOOST_TTI_DETAIL_UNION_HPP
9 
10 #include <boost/mpl/and.hpp>
11 #include <boost/mpl/apply.hpp>
12 #include <boost/mpl/bool.hpp>
13 #include <boost/mpl/eval_if.hpp>
14 #include <boost/mpl/has_xxx.hpp>
15 #include <boost/preprocessor/cat.hpp>
16 #include <boost/tti/detail/ddeftype.hpp>
17 #include <boost/tti/detail/dlambda.hpp>
18 #include <boost/tti/detail/denclosing_type.hpp>
19 #include <boost/tti/gen/namespace_gen.hpp>
20 #include <boost/type_traits/is_union.hpp>
21 
22 #define BOOST_TTI_DETAIL_TRAIT_INVOKE_HAS_UNION(trait,name) \
23 template<class BOOST_TTI_DETAIL_TP_T,class BOOST_TTI_DETAIL_TP_MFC> \
24 struct BOOST_PP_CAT(trait,_detail_union_invoke) \
25   { \
26   BOOST_MPL_ASSERT((BOOST_TTI_NAMESPACE::detail::is_lambda_expression<BOOST_TTI_DETAIL_TP_MFC>)); \
27   typedef typename boost::mpl::apply<BOOST_TTI_DETAIL_TP_MFC,typename BOOST_TTI_DETAIL_TP_T::name>::type type; \
28   }; \
29 /**/
30 
31 #define BOOST_TTI_DETAIL_TRAIT_HAS_UNION_OP_CHOOSE(trait,name) \
32 BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(BOOST_PP_CAT(trait,_detail_union_mpl), name, false) \
33 BOOST_TTI_DETAIL_TRAIT_INVOKE_HAS_UNION(trait,name) \
34 template<class BOOST_TTI_DETAIL_TP_T,class BOOST_TTI_DETAIL_TP_U,class BOOST_TTI_DETAIL_TP_B> \
35 struct BOOST_PP_CAT(trait,_detail_union_op_choose) : \
36   boost::mpl::and_ \
37     < \
38     boost::is_union<typename BOOST_TTI_DETAIL_TP_T::name>, \
39     BOOST_PP_CAT(trait,_detail_union_invoke)<BOOST_TTI_DETAIL_TP_T,BOOST_TTI_DETAIL_TP_U> \
40     > \
41   { \
42   }; \
43 \
44 template<class BOOST_TTI_DETAIL_TP_T,class BOOST_TTI_DETAIL_TP_U> \
45 struct BOOST_PP_CAT(trait,_detail_union_op_choose)<BOOST_TTI_DETAIL_TP_T,BOOST_TTI_DETAIL_TP_U,boost::mpl::false_::type> : \
46   boost::mpl::false_ \
47   { \
48   }; \
49 \
50 template<class BOOST_TTI_DETAIL_TP_T> \
51 struct BOOST_PP_CAT(trait,_detail_union_op_choose)<BOOST_TTI_DETAIL_TP_T,BOOST_TTI_NAMESPACE::detail::deftype,boost::mpl::true_::type> : \
52   boost::is_union<typename BOOST_TTI_DETAIL_TP_T::name> \
53   { \
54   }; \
55 /**/
56 
57 #define BOOST_TTI_DETAIL_TRAIT_HAS_UNION_OP(trait,name) \
58 BOOST_TTI_DETAIL_TRAIT_HAS_UNION_OP_CHOOSE(trait,name) \
59 template<class BOOST_TTI_DETAIL_TP_T,class BOOST_TTI_DETAIL_TP_U> \
60 struct BOOST_PP_CAT(trait,_detail_union_op) : \
61   BOOST_PP_CAT(trait,_detail_union_op_choose) \
62     < \
63     BOOST_TTI_DETAIL_TP_T, \
64     BOOST_TTI_DETAIL_TP_U, \
65     typename BOOST_PP_CAT(trait,_detail_union_mpl)<BOOST_TTI_DETAIL_TP_T>::type \
66     > \
67   { \
68   }; \
69 /**/
70 
71 #define BOOST_TTI_DETAIL_TRAIT_HAS_UNION(trait,name) \
72 BOOST_TTI_DETAIL_TRAIT_HAS_UNION_OP(trait,name) \
73 template<class BOOST_TTI_DETAIL_TP_T,class BOOST_TTI_DETAIL_TP_U> \
74 struct BOOST_PP_CAT(trait,_detail_union) : \
75     boost::mpl::eval_if \
76         < \
77         BOOST_TTI_NAMESPACE::detail::enclosing_type<BOOST_TTI_DETAIL_TP_T>, \
78         BOOST_PP_CAT(trait,_detail_union_op)<BOOST_TTI_DETAIL_TP_T,BOOST_TTI_DETAIL_TP_U>, \
79         boost::mpl::false_ \
80         > \
81   { \
82   }; \
83 /**/
84 
85 #endif // BOOST_TTI_DETAIL_UNION_HPP
86