tti_detail_has_type.qbk 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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_type Introspecting an inner type]
  8. The TTI macro [macroref BOOST_TTI_HAS_TYPE] introspects
  9. a nested type of a class.
  10. The BOOST_TTI_HAS_TYPE macro takes a single parameter which is the name of
  11. an inner type whose existence the programmer wants to check. The
  12. macro generates a metafunction called "has_type_'name_of_inner_type'".
  13. The main purpose of the generated metafunction is to check for the existence by
  14. name of the inner type. The metafunction can also be used to invoke an MPL lambda
  15. expression which is passed the inner type. One of the most common usages of the added
  16. functionality is to check whether or not the inner type is a typedef for another type.
  17. The metafunction is invoked by passing it the enclosing type
  18. to introspect. A second type may be passed to the
  19. metafunction, an MPL lambda expression taking the inner type
  20. and returning a boolean constant.
  21. The metafunction returns a single type called 'type', which is a
  22. boost::mpl::bool_. As a convenience the metafunction
  23. returns the value of this type directly as a compile time bool constant
  24. called 'value'. This value is true or false depending on whether the inner
  25. type exists or not.
  26. If a second optional type is passed, this type must be an MPL lambda expression
  27. and the expression will be invoked only if the inner type exists. In that case the
  28. metafunction returns true or false depending on whether the lambda expression returns
  29. true or false. If the inner type does not exist, the lambda expression, even if
  30. specified, is never invoked and the metafunction returns false.
  31. [heading Generating the metafunction]
  32. You generate the metafunction by invoking the macro with the name
  33. of an inner type:
  34. BOOST_TTI_HAS_TYPE(AType)
  35. generates a metafunction called 'has_type_AType' in the current scope.
  36. [heading Invoking the metafunction]
  37. You invoke the metafunction by instantiating the template with an enclosing
  38. type to introspect and, optionally, an MPL lambda expression.
  39. A return value called 'value' is a compile time bool constant.
  40. has_type_AType<Enclosing_Type>::value
  41. has_type_AType<Enclosing_Type,ALambdaExpression>::value
  42. [heading Examples]
  43. First we generate metafunctions for various inner type names:
  44. #include <boost/tti/has_type.hpp>
  45. BOOST_TTI_HAS_TYPE(MyTypeDef)
  46. BOOST_TTI_HAS_TYPE(AType)
  47. BOOST_TTI_HAS_TYPE(ATypeDef)
  48. BOOST_TTI_HAS_TYPE(MyType)
  49. Next let us create some user-defined types we want to introspect.
  50. struct Top
  51. {
  52. typedef int MyTypeDef;
  53. struct AType { };
  54. };
  55. struct Top2
  56. {
  57. typedef long ATypeDef;
  58. struct MyType { };
  59. };
  60. Finally we invoke our metafunction and return our value.
  61. has_type_MyTypeDef<Top>::value; // true
  62. has_type_MyTypeDef<Top2>::value; // false
  63. has_type_AType<Top>::value; // true
  64. has_type_AType<Top2>::value; // false
  65. has_type_ATypeDef<Top>::value; // false
  66. has_type_ATypeDef<Top2>::value; // true
  67. has_type_MyType<Top>::value; // false
  68. has_type_MyType<Top2>::value; // true
  69. [heading Examples - using lambda expressions]
  70. We can further invoke our metafunction with a second type,
  71. which is an MPL lambda expression.
  72. An MPL lambda expression, an extremely useful technique in
  73. template metaprogramming, allows us to pass a metafunction to
  74. other metafunctions. The metafunction we pass can be in the form
  75. of a placeholder expression or a metafunction class. In our case
  76. the metafunction passed to our has_type_'name_of_inner_type'
  77. metafunction as a lambda expression must return a boolean constant
  78. expression.
  79. [heading Example - using a lambda expression with a placeholder expression]
  80. We will first illustrate the use of a lambda expression in the
  81. form of a placeholder expression being passed as the second template
  82. parameter to our has_type_'name_of_inner_type' metafunction.
  83. A popular and simple placeholder expression we can use is
  84. 'boost::is_same<_1,SomeType>' to check if the inner type found is a
  85. particular type. This is particularly useful when the inner type
  86. is a typedef for some other type.
  87. First we include some more header files and a using declaration
  88. for convenience.
  89. #include <boost/mpl/placeholders.hpp
  90. #include <boost/type_traits/is_same.hpp
  91. using namespace boost::mpl::placeholders;
  92. Next we invoke our metafunction:
  93. has_type_MyTypeDef<Top,boost::is_same<_1,int> >::value; // true
  94. has_type_MyTypeDef<Top,boost::is_same<_1,long> >::value; // false
  95. has_type_ATypeDef<Top2,boost::is_same<_1,int> >::value; // false
  96. has_type_ATypeDef<Top2,boost::is_same<_1,long> >::value; // true
  97. [heading Example - using a lambda expression with a metafunction class]
  98. We will next illustrate the use of a lambda expression in the
  99. form of a metafunction class being passed as the second template
  100. parameter to our has_type_'name_of_inner_type' metafunction.
  101. A metafunction class is a type which has a nested class template
  102. called 'apply'. For our metafunction class example we will check if the
  103. inner type is a built-in integer type. First let us write out
  104. metafunction class:
  105. #include <boost/type_traits/is_integral.hpp>
  106. class OurMetafunctionClass
  107. {
  108. template<class T> struct apply :
  109. boost::is_integral<T>
  110. {
  111. };
  112. };
  113. Now we can invoke our metafunction:
  114. has_type_MyTypeDef<Top,OurMetafunctionClass>::value; // true
  115. has_type_AType<Top,OurMetafunctionClass>::value; // false
  116. has_type_ATypeDef<Top2,OurMetafunctionClass>::value; // true
  117. has_type_MyType<Top2,OurMetafunctionClass>::value; // true
  118. [heading Metafunction re-use]
  119. The macro encodes only the name of the inner type for which
  120. we are searching and the fact that we are introspecting for
  121. an inner type within an enclosing type.
  122. Because of this, once we create our metafunction for
  123. introspecting an inner type by name, we can reuse the
  124. metafunction for introspecting any enclosing type, having
  125. any inner type, for that name.
  126. Furthermore since we have only encoded the name of the inner
  127. type for which we are introspecting, we can not only introspect
  128. for that inner type by name but add different lambda expressions
  129. to inspect that inner type for whatever we want to find out about
  130. it using the same metafunction.
  131. [endsect]