]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/tti/doc/tti_detail_has_template.qbk
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / tti / doc / tti_detail_has_template.qbk
1 [/
2 (C) Copyright Edward Diener 2011,2012
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at
5 http://www.boost.org/LICENSE_1_0.txt).
6 ]
7
8 [section:tti_detail_has_template Introspecting an inner class template]
9
10 [section:tti_detail_has_template_macro Using the BOOST_TTI_HAS_TEMPLATE macro]
11
12 The TTI macro [macroref BOOST_TTI_HAS_TEMPLATE] introspects
13 an inner class template of a class. The macro must specify,
14 at the least, the name of the class template to introspect.
15
16 [heading Two forms of introspection]
17
18 There are two general forms of template introspection which can be used.
19 The first is to find a class template with any number of only
20 template type parameters ( template parameters starting with `class`
21 or `typename` ). In this form only the name of the class template
22 needs to be specified when invoking the macro. We will call this form
23 of the macro the `template type parameters` form. An example of a class
24 template of this form which could be successfully introspected would be:
25
26 template<class X,typename Y,class Z,typename T> class AClassTemplate { /* etc. */ };
27
28 The second is to find a class template with specific template parameters.
29 In this form both the name of the class template and the template parameters
30 are passed to the macro.
31
32 We will call this form of the macro the `specific parameters` form. An example
33 of a class template of this form which could be successfully introspected would be:
34
35 template<class X, template<class> class Y, int Z> BClassTemplate { /* etc. */ };
36
37 When using the specific form of the macro, there are two things which
38 need to be understood when passing the template parameters to the macro.
39 First, the actual names of the template parameters passed are irrelevant.
40 They can be left out completely or be different from the names in the
41 nested class template itself. Second, the use of 'typename' or 'class',
42 when referring to a template type parameter, is completely interchangeable,
43 as it is in the actual class template itself.
44
45 [heading Variadic and non-variadic macro usage]
46
47 When using the BOOST_TTI_HAS_TEMPLATE macro we distinguish between compilers
48 supporting variadic macros or not supporting variadic macros.
49
50 The programmer can always tell whether or not the compiler
51 supports variadic macros by checking the value of the macro
52 BOOST_PP_VARIADIC after including the necessary header file
53 `boost/tti/has_template.hpp` in order to use the BOOST_TTI_TEMPLATE
54 macro. A value of 1 indicates the compiler supports variadic macros
55 while a value of 0 indicates the compiler does not support variadic
56 macros.
57
58 Modern C++ compilers, in supporting the latest C++11 standard,
59 normally support variadic macros. Even before the latest C++11 standard
60 a number of C++ compilers already supported variadic macros. If you feel
61 your compiler supports variadic macros and BOOST_PP_VARIADIC is 0 even
62 after including `boost/tti/has_template.hpp`, you can predefine BOOST_PP_VARIADIC
63 to 1 before including `boost/tti/has_template.hpp`.
64
65 [heading Non-variadic macro usage]
66
67 We start with syntax for compilers not supporting variadic macros since this
68 syntax can also be used by compilers which do support variadic macros. The
69 form for non-variadic macros always takes two macro parameters. The first
70 macro parameter is always the name of the class template you are trying to
71 introspect.
72
73 The second macro parameter, when using the `specific parameters` form of the
74 macro, is the template parameters in the form of a Boost preprocessor library
75 array data type. When using the `template type parameters` form of the macro
76 the second macro parameter is BOOST_PP_NIL. If the second parameter is neither
77 a Boost preprocessor library array data type or BOOS_PP_NIL you will get a
78 compiler error if your compiler only supports non-variadic macros.
79
80 The non-variadic macro form for introspecting the class templates above
81 using the `template type parameters` form would be:
82
83 BOOST_TTI_TEMPLATE(AClassTemplate,BOOST_PP_NIL)
84 BOOST_TTI_TEMPLATE(BClassTemplate,BOOST_PP_NIL)
85
86 Invoking the metafunction in the second case would always fail since the
87 BClassTemplate does not have all template type parameters.
88
89 The non-variadic macro form for introspecting the class templates above
90 using the `specific parameters` form would be:
91
92 BOOST_TTI_TEMPLATE(AClassTemplate,(4,(class,typename,class,typename)))
93 BOOST_TTI_TEMPLATE(BClassTemplate,(3,(class, template<class> class, int)))
94
95 You need to be careful using the non-variadic `specific parameters` form
96 to specify the correct number of array parameters. This can sometimes be
97 tricky if you have a template template parameter, or a
98 non-type template parameter which has parentheses
99 surrounding part of the type specification. In the latter case,
100 when parentheses surround a comma ( ',' ), do not count that as
101 creating another Boost PP array token. Two examples:
102
103 template<void (*FunctionPointer)(int,long)> class CClassTemplate { /* etc. */ };
104 template<template<class,class> class T> class DClassTemplate { /* etc. */ };
105
106 BOOST_TTI_TEMPLATE(CClassTemplate,(1,(void (*)(int,long))))
107 BOOST_TTI_TEMPLATE(DClassTemplate,(2,(template<class,class> class)))
108
109 In the case of using the macro to introspect CClassTemplate the number of
110 Boost PP array parameters is 1, even though there is a comma separating
111 the tokens in `void (*FunctionPointer)(int,long)`. This is because the
112 comma is within parentheses.
113
114 In the case of using the macro to introspect DClassTemplate the number of
115 Boost PP array parameters is 2, because there is a comma separating the
116 tokens in `template<class,class> class T`.
117
118 [heading Variadic macro usage]
119
120 Having the ability to use variadic macros makes the syntax for using
121 BOOST_TTI_TEMPLATE easier to specify in both the `template type parameters`
122 form and the `specific parameters` form of using the macro.
123 This is because variadic macros can take a variable number of parameters.
124 When using the variadic macro form the first macro parameter is always the name
125 of the class template you are trying to introspect. You only specify
126 further parameters when using the `specific parameters` form of the macro,
127 in which case the further parameters to the macro are the specific template
128 parameters.
129
130 Introspecting the first class template above using the
131 `template type parameters` form the variadic macro would be:
132
133 BOOST_TTI_TEMPLATE(AClassTemplate)
134
135 Introspecting the other class templates above using the
136 `specific parameters` form the variadic macros would be:
137
138 BOOST_TTI_TEMPLATE(BClassTemplate,class,template<class> class, int)
139 BOOST_TTI_TEMPLATE(CClassTemplate,void (*)(int,long))
140 BOOST_TTI_TEMPLATE(DClassTemplate,template<class,class> class)
141
142 Here we have no problem with counting the number of tuple tokens
143 for the Boost PP array, nor do we have to specify BOOST_PP_NIL if
144 we are using the `template type parameters` form. Also for the
145 specific parameters form we simply use the template parameters as
146 the remaining tokens of the variadic macro.
147
148 [heading The resulting metafunction]
149
150 Using either form of the macro, whether using variadic or non-variadic
151 syntax, the macro generates a metafunction called
152 'has_template_'name_of_inner_class_template'.
153
154 The metafunction can be invoked by passing it the enclosing type
155 to introspect.
156
157 The metafunction returns a single type called 'type', which is a
158 boost::mpl::bool_. As a convenience the metafunction returns the
159 value of this type directly as a compile time bool constant
160 called 'value'. This is true or false depending on whether the inner
161 class template exists or not.
162
163 [endsect]
164
165 [section:tti_detail_has_template_metafunction Using the has_template_(xxx) metafunction]
166
167 [heading Generating the metafunction]
168
169 You generate the metafunction by invoking the macro with the name
170 of an inner class template:
171
172 // `template type parameters` form
173
174 BOOST_TTI_HAS_TEMPLATE(AClassTemplate,BOOST_PP_NIL) // non-variadic macro
175 BOOST_TTI_HAS_TEMPLATE(AClassTemplate) // variadic macro
176
177 // `specific parameters` form
178
179 BOOST_TTI_HAS_TEMPLATE(AClassTemplate,(2,(class,int))) // non-variadic macro
180 BOOST_TTI_HAS_TEMPLATE(AClassTemplate,class,int) // variadic macro
181
182 generates a metafunction called 'has_template_AClassTemplate' in the current scope.
183
184 If you want to introspect the same class template name using both the
185 `template type parameters` form and the `specific parameters` form
186 you will have the problem that you will be generating a metafunction
187 of the same name and violating the C++ ODR rule. In this particular
188 case you can use the alternate BOOST_TTI_TRAIT_HAS_TEMPLATE macro
189 to name the particular metafunction which will be generated.
190
191 [heading Invoking the metafunction]
192
193 You invoke the metafunction by instantiating the template with an enclosing
194 type to introspect. A return value called 'value' is a compile time bool constant.
195
196 has_template_AType<Enclosing_Type>::value
197
198 [heading Examples]
199
200 First we generate metafunctions for various inner class template names:
201
202 #include <boost/tti/has_template.hpp>
203
204 // Using variadic macro, `template type parameters`
205
206 BOOST_TTI_HAS_TEMPLATE(Template1)
207 BOOST_TTI_HAS_TEMPLATE(Template2)
208 BOOST_TTI_HAS_TEMPLATE(Template3)
209 BOOST_TTI_HAS_TEMPLATE(Template4)
210 BOOST_TTI_HAS_TEMPLATE(Template5)
211
212 // or using non-variadic macro, `template type parameters`
213
214 BOOST_TTI_HAS_TEMPLATE(Template1,BOOST_PP_NIL)
215 BOOST_TTI_HAS_TEMPLATE(Template2,BOOST_PP_NIL)
216 BOOST_TTI_HAS_TEMPLATE(Template3,BOOST_PP_NIL)
217 BOOST_TTI_HAS_TEMPLATE(Template4,BOOST_PP_NIL)
218 BOOST_TTI_HAS_TEMPLATE(Template5,BOOST_PP_NIL)
219
220 // Using variadic macro, `specific parameters`
221
222 BOOST_TTI_HAS_TEMPLATE(Template6,class,int)
223 BOOST_TTI_HAS_TEMPLATE(Template7,typename,template<class,class> struct,long)
224 BOOST_TTI_HAS_TEMPLATE(Template8,double,typename)
225 BOOST_TTI_HAS_TEMPLATE(Template9,typename,class,typename,class,typename,short)
226
227 // or using non-variadic macro, `specific parameters`
228
229 BOOST_TTI_HAS_TEMPLATE(Template6,(2,(class,int)))
230 BOOST_TTI_HAS_TEMPLATE(Template7,(4,(typename,template<class,class> struct,long)))
231 BOOST_TTI_HAS_TEMPLATE(Template8,(2,(double,typename)))
232 BOOST_TTI_HAS_TEMPLATE(Template9,(6,(typename,class,typename,class,typename,short)))
233
234 Next let us create some user-defined types we want to introspect.
235
236 struct Top
237 {
238 template <class X> struct Template1 { };
239 template <typename A,typename B,typename C> class Template2 { };
240 template <typename A,typename B,typename C,int D> class Template3 { };
241 };
242 struct Top2
243 {
244 template <typename A,typename B,typename C,class D> class Template3 { };
245 template <class X,typename Y> struct Template4 { };
246 template <typename A,class B,typename C,class D,typename E> class Template5 { };
247 };
248 struct Top3
249 {
250 template <class X,int Y> struct Template6 { };
251 template <typename A,template<class,class> struct B,long C> class Template7 { };
252 };
253 struct Top4
254 {
255 template <double X,typename Y> struct Template8 { };
256 template <typename A,class B,typename C,class D,typename E,short F> class Template9 { };
257 };
258
259 Finally we invoke our metafunction and return our value.
260 This all happens at compile time, and can be used by
261 programmers doing compile time template metaprogramming.
262
263 has_template_Template1<Top>::value; // true
264 has_template_Template1<Top2>::value; // false
265
266 has_template_Template2<Top>::value; // true
267 has_template_Template2<Top2>::value; // false
268
269 has_template_Template3<Top>::value; // false, not all typename/class template parameters
270 has_template_Template3<Top2>::value; // true
271
272 has_template_Template4<Top>::value; // false
273 has_template_Template4<Top2>::value; // true
274
275 has_template_Template5<Top>::value; // false
276 has_template_Template5<Top2>::value; // true
277
278 has_template_Template6<Top3>::value; // true
279 has_template_Template6<Top4>::value; // false
280
281 has_template_Template7<Top3>::value; // true
282 has_template_Template7<Top4>::value; // false
283
284 has_template_Template8<Top3>::value; // false
285 has_template_Template8<Top4>::value; // true
286
287 has_template_Template9<Top3>::value; // false
288 has_template_Template9<Top4>::value; // true
289
290 [heading Metafunction re-use]
291
292 The macro encodes the name of the inner class template for
293 which we are searching, the fact that we are introspecting for
294 a class template within an enclosing type, and optionally the
295 template parameters for that class template.
296
297 Once we create our metafunction for introspecting an inner class
298 template by name, we can reuse the metafunction for introspecting
299 any enclosing type, having any inner class template, for that name.
300
301 However we need to understand that we are restricted in our reuse
302 of the metafunction by whether we originally use the template type
303 parameters form or the specific form. In either case we are always
304 introspecting an inner class template which matches that form.
305 In the case of the template type parameters form, any inner class
306 template for which we are introspecting must have all template type
307 parameters, as well as the correct name. In the case of the specific
308 parameters form, any inner class template for which we are
309 introspecting must have template parameters which match the specific
310 template parameters passed to the macro, as well as the correct name.
311
312 [endsect]
313
314 [endsect]