tti_functionality.qbk 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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_functionality General Functionality]
  8. The elements of a type about which a template metaprogrammer might be interested in finding
  9. out at compile time are:
  10. * Does it have a nested type with a particular name ?
  11. * Does it have a nested type with a particular name which fulfills some other possibility for that nested type.
  12. * Does it have a nested class template with a particular name ?
  13. * Does it have a nested class template with a particular name and a particular signature ?
  14. * Does it have a member function with a particular name and a particular signature ?
  15. * Does it have member data with a particular name and of a particular type ?
  16. * Does it have a static member function with a particular name and a particular signature ?
  17. * Does it have static member data with a particular name and of a particular type ?
  18. * Does it have either member data or static member data with a particular name and of a particular type ?
  19. * Does it have either a member function or static member function with a particular name and of a particular type ?
  20. These are some of the compile-time questions which the TTI library answers. It
  21. does this by creating metafunctions, which can be used at compile-time, using
  22. C++ macros. Each of the metafunctions created returns a compile time constant
  23. bool value which answers one of the above questions at compile time. When the
  24. particular element above exists the value is 'true', or more precisely
  25. boost::mpl::true_, while if the element does not exist the value is 'false',
  26. or more precisely boost::mpl::false_. In either case the type of this value
  27. is boost::mpl::bool_.
  28. This constant bool value, in the terminology of the Boost MPL library, is called an 'integral
  29. constant wrapper' and the metafunction generated is called a 'numerical metafunction'. The
  30. results from calling the metafunction can be passed to other metafunctions for type selection,
  31. the most popular of these being the boolean-valued operators in the Boost MPL library.
  32. All of the questions above attempt to find an answer about an inner element with
  33. a particular name. In order to do this using template metaprogramming, macros are used
  34. so that the name of the inner element can be passed to the macro. The macro will then
  35. generate an appropriate metafunction, which the template metaprogrammer can then use to
  36. introspect the information that is needed. The name itself of the inner element is always passed
  37. to the macro as a macro parameter, but other macro parameters may also be needed in some cases.
  38. All of the macros start with the prefix `BOOST_TTI_`, create their metafunctions as class
  39. templates in whatever scope the user invokes the macro, and come in two forms:
  40. # In the simplest macro form, which I call the simple macro form, the 'name' of the inner element
  41. is used directly to generate the name of the metafunction as well as serving as the 'name'
  42. to introspect. In generating the name of the metafunction from the macro name, the
  43. `BOOST_TTI_` prefix is removed, the rest of the macro name is changed to lower case, and an
  44. underscore ( '_' ) followed by the 'name' is appended. As an example, for the macro
  45. `BOOST_TTI_HAS_TYPE(MyType)` the name of the metafunction is `has_type_MyType` and it will
  46. look for an inner type called 'MyType'.
  47. # In a more complicated macro form, which I call the complex macro form, the macro starts with
  48. `BOOST_TTI_TRAIT_` and a 'trait' name is passed as the first parameter, with the 'name' of the inner
  49. element as the second parameter. The 'trait' name serves solely to completely name the metafunction in
  50. whatever scope the macro is invoked. As an example, for the macro
  51. `BOOST_TTI_TRAIT_HAS_TYPE(MyTrait,MyType)` the name of
  52. the metafunction is `MyTrait` and it will look for an inner type called `MyType`.
  53. Every macro metafunction has a simple macro form and a corresponding complex macro form.
  54. Once either of these two macro forms are used for a particular type of inner element, the
  55. corresponding macro metafunction works exactly the same way and has the exact same functionality.
  56. In the succeeding documentation all macro metafunctions will be referred by their simple form
  57. name, but remember that the complex form can always be used instead. The complex form is useful
  58. whenever using the simple form could create a duplicate name in the same name space, thereby
  59. violating the C++ one definition rule.
  60. [heading Macro Metafunction Name Generation]
  61. For the simple macro form, even though it is fairly easy to remember the algorithm by which
  62. the generated metafunction is named, TTI also provides, for each macro metafunction,
  63. a corresponding 'naming' macro which the end-user can use and whose sole purpose
  64. is to expand to the metafunction name. The naming macro for each macro metafunction has the form:
  65. 'corresponding-macro'_GEN(name).
  66. As an example, BOOST_TTI_HAS_TYPE(MyType) creates a metafunction
  67. which looks for a nested type called 'MyType' within some enclosing type. The name of the metafunction
  68. generated, given our rule above is 'has_type_MyType'. A corresponding macro called
  69. BOOST_TTI_HAS_TYPE_GEN, invoked as BOOST_TTI_HAS_TYPE_GEN(MyType) in our example, expands to the
  70. same 'has_type_MyType' name. These name generating macros, for each of the metafunction generating macros,
  71. are purely a convenience for end-users who find using them easier than remembering the name-generating
  72. rule given above.
  73. [section:tti_functionality_nm_gen Macro metafunction name generation considerations]
  74. Because having a double underscore ( __ ) in a name is reserved by the C++ implementation,
  75. creating C++ identifiers with double underscores should be avoided by the end-user. When using
  76. a TTI macro to generate a metafunction using the simple macro form, TTI appends a single
  77. underscore to the macro name preceding the name of the element that is being introspected.
  78. The reason for doing this is because Boost discourages as non-portable C++ identifiers with mixed
  79. case letters and the underscore then becomes the normal way to separate parts of an identifier
  80. name so that it looks understandable. Because of this decision to use the underscore to generate
  81. the metafunction name from the macro name, any inner element starting with an underscore will cause
  82. the identifier for the metafunction name being generated to contain a double underscore.
  83. A rule to avoid this problem is:
  84. * When the name of the inner element to be introspected begins with an underscore, use
  85. the complex macro form, where the name of the metafunction is specifically given.
  86. Furthermore because TTI often generates not only a metafunction for the end-user to use but some
  87. supporting detail metafunctions whose identifier, for reasons of programming clarity, is the same
  88. as the metafunction with further letters appended to it separated by an underscore, another rule is:
  89. * When using the complex macro form, which fully gives the name of the generated
  90. macro metafunction, that name should not end with an underscore.
  91. Following these two simple rules will avoid names with double underscores being
  92. generated by TTI.
  93. [heading Reusing the named metafunction]
  94. When the end-user uses the TTI macros to generate a metafunction for introspecting an inner
  95. element of a particular type, that metafunction can be re-used with any combination of valid
  96. template parameters which involve the same type of inner element of a particular name.
  97. As one example of this let's consider two different types called
  98. 'AType' and 'BType', for each of which we want to determine whether an inner type called
  99. 'InnerType' exists. For both these types we need only generate a single macro metafunction in
  100. the current scope by using:
  101. BOOST_TTI_HAS_TYPE(InnerType)
  102. We now have a metafunction, which is a C++ class template, in the current scope whose C++ identifier
  103. is 'has_type_InnerType'. We can use this same metafunction to introspect the existence of the nested type
  104. 'InnerType' in either 'AType' or 'BType' at compile time. Although the syntax for doing this has no yet
  105. been explained, I will give it here so that you can see how 'has_type_InnerType' is reused:
  106. # 'has_type_InnerType<AType>::value' is a compile time constant telling us whether 'InnerType' is a
  107. type which is nested within 'AType'.
  108. # 'has_type_InnerType<BType>::value' is a compile time constant telling us whether 'InnerType' is a
  109. type which is nested within 'BType'.
  110. As another example of metafunction reuse let's consider a single type, called 'CType', for which we want to
  111. determine if it has either of two overloaded member functions with the same name of 'AMemberFunction'
  112. but with the different function signatures of 'int (int)' and 'double (long)'. For both these
  113. member functions we need only generate a single macro metafunction in the current scope by using:
  114. BOOST_TTI_HAS_MEMBER_FUNCTION(AMemberFunction)
  115. We now have a metafunction, which is a C++ class template, in the current scope whose C++ identifier
  116. is 'has_member_function_AMemberFunction'. We can use this same metafunction to introspect the
  117. existence of the member function 'AMemberFunction' with either the function signature of
  118. 'int (int)' or 'double (long)' in 'CType' at compile time. Although the syntax for doing this has no yet
  119. been explained, I will give it here so that you can see how 'has_type_InnerType' is reused:
  120. # 'has_member_function_AMemberFunction<CType,int,boost::mpl::vector<int> >::value' is a
  121. compile time constant telling us whether 'AMemberFunction' is a member function of type 'CType'
  122. whose function signature is 'int (int)'.
  123. # 'has_member_function_AMemberFunction<CType,double,boost::mpl::vector<long> >::value' is a
  124. compile time constant telling us whether 'AMemberFunction' is a member function of type 'CType'
  125. whose function signature is 'double (long)'.
  126. These are just two examples of the ways a particular macro metafunction can be reused. The two
  127. 'constants' when generating a macro metafunction are the 'name' and 'type of inner element'. Once
  128. the macro metafunction for a particular name and inner element type has been generated, it can be reused
  129. for introspecting the inner element(s) of any enclosing type which correspond to that name and
  130. inner element type.
  131. [heading Avoiding ODR violations]
  132. The TTI macro metafunctions are generating directly in the enclosing scope in which the
  133. corresponding macro is invoked. This can be any C++ scope in which a class template can
  134. be specified. Within this enclosing scope the name of the metafunction
  135. being generated must be unique or else a C++ ODR ( One Definition Rule ) violation will occur.
  136. This is extremely important to remember, especially when the enclosing scope can occur in
  137. more than one translation unit, which is the case for namespaces and the global scope.
  138. Because of ODR, and the way that the simple macro form metafunction name is directly dependent
  139. on the inner element and name of the element being introspected, it is the responsibility of the
  140. programmer using the TTI macros to generate metafunctions to avoid ODR within a module
  141. ( application or library ). There are a few general methods for doing this:
  142. # Create unique namespace names in which to generate the macro metafunctions and/or generate
  143. the macro metafunctions in C++ scopes which can not extend across translation units. The most
  144. obvious example of this latter is within C++ classes.
  145. # Use the complex macro form to specifically name the metafunction generated in order to
  146. provide a unique name.
  147. # Avoid using the TTI macros in the global scope.
  148. For anyone using TTI in a library which others will eventually use, it is important
  149. to generate metafunction names which are unique to that library.
  150. TTI also reserves not only the name generated by the macro metafunction for its use
  151. but also any C++ identifier sequence which begins with that name. In other words
  152. if the metafunction being generated by TTI is named 'MyMetafunction' using the complex
  153. macro form, do not create any C++ construct with an identifier starting with 'MyMetaFunction',
  154. such as 'MyMetaFunction_Enumeration' or 'MyMetaFunctionHelper' in the same scope.
  155. All names starting with the metafunction name in the current scope should be considered
  156. out of bounds for the programmer using TTI.
  157. [endsect]
  158. [endsect]