tti_detail_has_template.qbk 13 KB

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