PageRenderTime 24ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llcommon/ll_template_cast.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 177 lines | 33 code | 6 blank | 138 comment | 0 complexity | 5821f8fd560ef44bb10c7bf0390a6179 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file ll_template_cast.h
  3. * @author Nat Goodspeed
  4. * @date 2009-11-21
  5. * @brief Define ll_template_cast function
  6. *
  7. * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  8. * Second Life Viewer Source Code
  9. * Copyright (C) 2010, Linden Research, Inc.
  10. *
  11. * This library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation;
  14. * version 2.1 of the License only.
  15. *
  16. * This library is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with this library; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  26. * $/LicenseInfo$
  27. */
  28. #if ! defined(LL_LL_TEMPLATE_CAST_H)
  29. #define LL_LL_TEMPLATE_CAST_H
  30. /**
  31. * Implementation for ll_template_cast() (q.v.).
  32. *
  33. * Default implementation: trying to cast two completely unrelated types
  34. * returns 0. Typically you'd specify T and U as pointer types, but in fact T
  35. * can be any type that can be initialized with 0.
  36. */
  37. template <typename T, typename U>
  38. struct ll_template_cast_impl
  39. {
  40. T operator()(U)
  41. {
  42. return 0;
  43. }
  44. };
  45. /**
  46. * ll_template_cast<T>(some_value) is for use in a template function when
  47. * some_value might be of arbitrary type, but you want to recognize type T
  48. * specially.
  49. *
  50. * It's designed for use with pointer types. Example:
  51. * @code
  52. * struct SpecialClass
  53. * {
  54. * void someMethod(const std::string&) const;
  55. * };
  56. *
  57. * template <class REALCLASS>
  58. * void somefunc(const REALCLASS& instance)
  59. * {
  60. * const SpecialClass* ptr = ll_template_cast<const SpecialClass*>(&instance);
  61. * if (ptr)
  62. * {
  63. * ptr->someMethod("Call method only available on SpecialClass");
  64. * }
  65. * }
  66. * @endcode
  67. *
  68. * Why is this better than dynamic_cast<>? Because unless OtherClass is
  69. * polymorphic, the following won't even compile (gcc 4.0.1):
  70. * @code
  71. * OtherClass other;
  72. * SpecialClass* ptr = dynamic_cast<SpecialClass*>(&other);
  73. * @endcode
  74. * to say nothing of this:
  75. * @code
  76. * void function(int);
  77. * SpecialClass* ptr = dynamic_cast<SpecialClass*>(&function);
  78. * @endcode
  79. * ll_template_cast handles these kinds of cases by returning 0.
  80. */
  81. template <typename T, typename U>
  82. T ll_template_cast(U value)
  83. {
  84. return ll_template_cast_impl<T, U>()(value);
  85. }
  86. /**
  87. * Implementation for ll_template_cast() (q.v.).
  88. *
  89. * Implementation for identical types: return same value.
  90. */
  91. template <typename T>
  92. struct ll_template_cast_impl<T, T>
  93. {
  94. T operator()(T value)
  95. {
  96. return value;
  97. }
  98. };
  99. /**
  100. * LL_TEMPLATE_CONVERTIBLE(dest, source) asserts that, for a value @c s of
  101. * type @c source, <tt>ll_template_cast<dest>(s)</tt> will return @c s --
  102. * presuming that @c source can be converted to @c dest by the normal rules of
  103. * C++.
  104. *
  105. * By default, <tt>ll_template_cast<dest>(s)</tt> will return 0 unless @c s's
  106. * type is literally identical to @c dest. (This is because of the
  107. * straightforward application of template specialization rules.) That can
  108. * lead to surprising results, e.g.:
  109. *
  110. * @code
  111. * Foo myFoo;
  112. * const Foo* fooptr = ll_template_cast<const Foo*>(&myFoo);
  113. * @endcode
  114. *
  115. * Here @c fooptr will be 0 because <tt>&myFoo</tt> is of type <tt>Foo*</tt>
  116. * -- @em not <tt>const Foo*</tt>. (Declaring <tt>const Foo myFoo;</tt> would
  117. * force the compiler to do the right thing.)
  118. *
  119. * More disappointingly:
  120. * @code
  121. * struct Base {};
  122. * struct Subclass: public Base {};
  123. * Subclass object;
  124. * Base* ptr = ll_template_cast<Base*>(&object);
  125. * @endcode
  126. *
  127. * Here @c ptr will be 0 because <tt>&object</tt> is of type
  128. * <tt>Subclass*</tt> rather than <tt>Base*</tt>. We @em want this cast to
  129. * succeed, but without our help ll_template_cast can't recognize it.
  130. *
  131. * The following would suffice:
  132. * @code
  133. * LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
  134. * ...
  135. * Base* ptr = ll_template_cast<Base*>(&object);
  136. * @endcode
  137. *
  138. * However, as noted earlier, this is easily fooled:
  139. * @code
  140. * const Base* ptr = ll_template_cast<const Base*>(&object);
  141. * @endcode
  142. * would still produce 0 because we haven't yet seen:
  143. * @code
  144. * LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
  145. * @endcode
  146. *
  147. * @TODO
  148. * This macro should use Boost type_traits facilities for stripping and
  149. * re-adding @c const and @c volatile qualifiers so that invoking
  150. * LL_TEMPLATE_CONVERTIBLE(dest, source) will automatically generate all
  151. * permitted permutations. It's really not fair to the coder to require
  152. * separate:
  153. * @code
  154. * LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
  155. * LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
  156. * LL_TEMPLATE_CONVERTIBLE(const Base*, const Subclass*);
  157. * @endcode
  158. *
  159. * (Naturally we omit <tt>LL_TEMPLATE_CONVERTIBLE(Base*, const Subclass*)</tt>
  160. * because that's not permitted by normal C++ assignment anyway.)
  161. */
  162. #define LL_TEMPLATE_CONVERTIBLE(DEST, SOURCE) \
  163. template <> \
  164. struct ll_template_cast_impl<DEST, SOURCE> \
  165. { \
  166. DEST operator()(SOURCE wrapper) \
  167. { \
  168. return wrapper; \
  169. } \
  170. }
  171. #endif /* ! defined(LL_LL_TEMPLATE_CAST_H) */