1 
2 //  (C) Copyright Edward Diener 2011,2012,2013
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_MEMBER_TYPE_HPP)
8 #define BOOST_TTI_MEMBER_TYPE_HPP
9 
10 #include <boost/mpl/eval_if.hpp>
11 #include <boost/mpl/identity.hpp>
12 #include <boost/mpl/not.hpp>
13 #include <boost/type_traits/is_same.hpp>
14 #include <boost/preprocessor/cat.hpp>
15 #include <boost/tti/gen/member_type_gen.hpp>
16 #include <boost/tti/gen/namespace_gen.hpp>
17 #include <boost/tti/detail/dmem_type.hpp>
18 #include <boost/tti/detail/dnotype.hpp>
19 
20 /*
21 
22   The succeeding comments in this file are in doxygen format.
23 
24 */
25 
26 /** \file
27 */
28 
29 /// A macro expands to a metafunction whose typedef 'type' is either the named type or a marker type.
30 /**
31 
32     BOOST_TTI_TRAIT_MEMBER_TYPE is a macro which expands to a metafunction.
33     The metafunction tests whether an inner type with a particular name exists
34     by returning the inner type or a marker type.
35     The macro takes the form of BOOST_TTI_TRAIT_MEMBER_TYPE(trait,name) where
36 
37     trait = the name of the metafunction <br/>
38     name  = the name of the inner type.
39 
40     BOOST_TTI_TRAIT_MEMBER_TYPE generates a metafunction called "trait" where 'trait' is the macro parameter.
41 
42   @code
43 
44               template<class BOOST_TTI_TP_T,class BOOST_TTI_TP_MARKER_TYPE = boost::tti::detail::notype>
45               struct trait
46                 {
47                 typedef unspecified type;
48                 typedef BOOST_TTI_TP_MARKER_TYPE boost_tti_marker_type;
49                 };
50 
51               The metafunction types and return:
52 
53                 BOOST_TTI_TP_T           = the enclosing type.
54                                            The enclosing type can be a class, struct, or union.
55 
56                 BOOST_TTI_TP_MARKER_TYPE = (optional) a type to use as the marker type.
57                                            defaults to the internal boost::tti::detail::notype.
58 
59                 returns                  = 'type' is the inner type of 'name' if the inner type exists
60                                            within the enclosing type, else 'type' is a marker type.
61                                            if the end-user does not specify a marker type then
62                                            an internal boost::tti::detail::notype marker type,
63                                            which is empty, is used.
64 
65                 The metafunction also encapsulates the type of the marker type as
66                 a nested 'boost_tti_marker_type'.
67 
68   @endcode
69 
70     The purpose of this macro is to encapsulate the 'name' type as the typedef 'type'
71     of a metafunction, but only if it exists within the enclosing type. This allows for
72     an evaluation of inner type existence, without generating a compiler error,
73     which can be used by other metafunctions in this library.
74 
75 */
76 #define BOOST_TTI_TRAIT_MEMBER_TYPE(trait,name) \
77     BOOST_TTI_DETAIL_TRAIT_HAS_TYPE_MEMBER_TYPE(trait,name) \
78     BOOST_TTI_DETAIL_TRAIT_MEMBER_TYPE(trait,name) \
79     template<class BOOST_TTI_TP_T,class BOOST_TTI_TP_MARKER_TYPE = BOOST_TTI_NAMESPACE::detail::notype> \
80     struct trait : \
81       boost::mpl::eval_if \
82         < \
83         BOOST_PP_CAT(trait,_detail_has_type_member_type)<BOOST_TTI_TP_T>, \
84         BOOST_PP_CAT(trait,_detail_member_type)<BOOST_TTI_TP_T>, \
85         boost::mpl::identity<BOOST_TTI_TP_MARKER_TYPE> \
86         > \
87       { \
88       typedef BOOST_TTI_TP_MARKER_TYPE boost_tti_marker_type; \
89       }; \
90 /**/
91 
92 /// A macro which expands to a metafunction whose typedef 'type' is either the named type or a marker type.
93 /**
94 
95     BOOST_TTI_MEMBER_TYPE is a macro which expands to a metafunction.
96     The metafunction tests whether an inner type with a particular name exists
97     by returning the inner type or a marker type.
98     The macro takes the form of BOOST_TTI_MEMBER_TYPE(name) where
99 
100     name  = the name of the inner type.
101 
102     BOOST_TTI_MEMBER_TYPE generates a metafunction called "member_type_name" where 'name' is the macro parameter.
103 
104   @code
105 
106               template<class BOOST_TTI_TP_T,class BOOST_TTI_TP_MARKER_TYPE = boost::tti::detail::notype>
107               struct member_type_'name'
108                 {
109                 typedef unspecified type;
110                 typedef BOOST_TTI_TP_MARKER_TYPE boost_tti_marker_type;
111                 };
112 
113               The metafunction types and return:
114 
115                 BOOST_TTI_TP_T           = the enclosing type.
116                                            The enclosing type can be a class, struct, or union.
117 
118                 BOOST_TTI_TP_MARKER_TYPE = (optional) a type to use as the marker type.
119                                            defaults to the internal boost::tti::detail::notype.
120 
121                 returns                  = 'type' is the inner type of 'name' if the inner type exists
122                                            within the enclosing type, else 'type' is a marker type.
123                                            if the end-user does not specify a marker type then
124                                            an internal boost::tti::detail::notype marker type is used.
125 
126                 The metafunction also encapsulates the type of the marker type as
127                 a nested 'boost_tti_marker_type'.
128 
129   @endcode
130 
131     The purpose of this macro is to encapsulate the 'name' type as the typedef 'type'
132     of a metafunction, but only if it exists within the enclosing type. This allows for
133     an evaluation of inner type existence, without generating a compiler error,
134     which can be used by other metafunctions in this library.
135 
136 */
137 #define BOOST_TTI_MEMBER_TYPE(name) \
138   BOOST_TTI_TRAIT_MEMBER_TYPE \
139   ( \
140   BOOST_TTI_MEMBER_TYPE_GEN(name), \
141   name \
142   ) \
143 /**/
144 
145 namespace boost
146   {
147   namespace tti
148     {
149 
150     /// A metafunction which checks whether the member 'type' returned from invoking the macro metafunction generated by BOOST_TTI_MEMBER_TYPE ( BOOST_TTI_TRAIT_MEMBER_TYPE ) is a valid type.
151     /**
152 
153         The metafunction 'valid_member_type', which is in the boost::tti namespace, takes the form of:
154 
155   @code
156 
157         template<class BOOST_TTI_TP_T,class BOOST_TTI_TP_MARKER_TYPE = boost::tti::detail::notype>
158         struct valid_member_type
159           {
160           static const value = unspecified;
161           typedef mpl::bool_<true-or-false> type;
162           };
163 
164         The metafunction types and return:
165 
166           BOOST_TTI_TP_T           = returned inner 'type' from invoking the macro metafunction generated by BOOST_TTI_MEMBER_TYPE ( BOOST_TTI_TRAIT_MEMBER_TYPE ).
167 
168           BOOST_TTI_TP_MARKER_TYPE = (optional) a type to use as the marker type.
169                                      defaults to the internal boost::tti::detail::notype.
170 
171           returns                  = 'value' is true if the type is valid, otherwise 'value' is false.
172                                      A valid type means that the returned inner 'type' is not the marker type.
173 
174   @endcode
175 
176     */
177     template<class BOOST_TTI_TP_T,class BOOST_TTI_TP_MARKER_TYPE = BOOST_TTI_NAMESPACE::detail::notype>
178     struct valid_member_type :
179       boost::mpl::not_
180         <
181         boost::is_same<BOOST_TTI_TP_T,BOOST_TTI_TP_MARKER_TYPE>
182         >
183       {
184       };
185 
186     /// A metafunction which checks whether the invoked macro metafunction generated by BOOST_TTI_MEMBER_TYPE ( BOOST_TTI_TRAIT_MEMBER_TYPE ) hold a valid type.
187     /**
188 
189         The metafunction 'valid_member_metafunction', which is in the boost::tti namespace, takes the form of:
190 
191   @code
192 
193         template<class BOOST_TTI_METAFUNCTION>
194         struct valid_member_metafunction
195           {
196           static const value = unspecified;
197           typedef mpl::bool_<true-or-false> type;
198           };
199 
200         The metafunction types and return:
201 
202           BOOST_TTI_METAFUNCTION = The invoked macro metafunction generated by BOOST_TTI_MEMBER_TYPE ( BOOST_TTI_TRAIT_MEMBER_TYPE ).
203 
204           returns          = 'value' is true if the nested type of the invoked metafunction is valid, otherwise 'value' is false.
205                              A valid type means that the invoked metafunction's inner 'type' is not the marker type.
206 
207   @endcode
208 
209     */
210     template<class BOOST_TTI_METAFUNCTION>
211     struct valid_member_metafunction :
212       boost::mpl::not_
213         <
214         boost::is_same<typename BOOST_TTI_METAFUNCTION::type,typename BOOST_TTI_METAFUNCTION::boost_tti_marker_type>
215         >
216       {
217       };
218     }
219   }
220 
221 #endif // BOOST_TTI_MEMBER_TYPE_HPP
222