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