ll_template_cast.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:6k
源码类别:

游戏引擎

开发平台:

C++ Builder

  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=viewergpl$
  8.  * 
  9.  * Copyright (c) 2009-2010, Linden Research, Inc.
  10.  * 
  11.  * Second Life Viewer Source Code
  12.  * The source code in this file ("Source Code") is provided by Linden Lab
  13.  * to you under the terms of the GNU General Public License, version 2.0
  14.  * ("GPL"), unless you have obtained a separate licensing agreement
  15.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  16.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18.  * 
  19.  * There are special exceptions to the terms and conditions of the GPL as
  20.  * it is applied to this Source Code. View the full text of the exception
  21.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  22.  * online at
  23.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24.  * 
  25.  * By copying, modifying or distributing this software, you acknowledge
  26.  * that you have read and understood your obligations described above,
  27.  * and agree to abide by those obligations.
  28.  * 
  29.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31.  * COMPLETENESS OR PERFORMANCE.
  32.  * $/LicenseInfo$
  33.  */
  34. #if ! defined(LL_LL_TEMPLATE_CAST_H)
  35. #define LL_LL_TEMPLATE_CAST_H
  36. /**
  37.  * Implementation for ll_template_cast() (q.v.).
  38.  *
  39.  * Default implementation: trying to cast two completely unrelated types
  40.  * returns 0. Typically you'd specify T and U as pointer types, but in fact T
  41.  * can be any type that can be initialized with 0.
  42.  */
  43. template <typename T, typename U>
  44. struct ll_template_cast_impl
  45. {
  46.     T operator()(U)
  47.     {
  48.         return 0;
  49.     }
  50. };
  51. /**
  52.  * ll_template_cast<T>(some_value) is for use in a template function when
  53.  * some_value might be of arbitrary type, but you want to recognize type T
  54.  * specially.
  55.  *
  56.  * It's designed for use with pointer types. Example:
  57.  * @code
  58.  * struct SpecialClass
  59.  * {
  60.  *     void someMethod(const std::string&) const;
  61.  * };
  62.  *
  63.  * template <class REALCLASS>
  64.  * void somefunc(const REALCLASS& instance)
  65.  * {
  66.  *     const SpecialClass* ptr = ll_template_cast<const SpecialClass*>(&instance);
  67.  *     if (ptr)
  68.  *     {
  69.  *         ptr->someMethod("Call method only available on SpecialClass");
  70.  *     }
  71.  * }
  72.  * @endcode
  73.  *
  74.  * Why is this better than dynamic_cast<>? Because unless OtherClass is
  75.  * polymorphic, the following won't even compile (gcc 4.0.1):
  76.  * @code
  77.  * OtherClass other;
  78.  * SpecialClass* ptr = dynamic_cast<SpecialClass*>(&other);
  79.  * @endcode
  80.  * to say nothing of this:
  81.  * @code
  82.  * void function(int);
  83.  * SpecialClass* ptr = dynamic_cast<SpecialClass*>(&function);
  84.  * @endcode
  85.  * ll_template_cast handles these kinds of cases by returning 0.
  86.  */
  87. template <typename T, typename U>
  88. T ll_template_cast(U value)
  89. {
  90.     return ll_template_cast_impl<T, U>()(value);
  91. }
  92. /**
  93.  * Implementation for ll_template_cast() (q.v.).
  94.  *
  95.  * Implementation for identical types: return same value.
  96.  */
  97. template <typename T>
  98. struct ll_template_cast_impl<T, T>
  99. {
  100.     T operator()(T value)
  101.     {
  102.         return value;
  103.     }
  104. };
  105. /**
  106.  * LL_TEMPLATE_CONVERTIBLE(dest, source) asserts that, for a value @c s of
  107.  * type @c source, <tt>ll_template_cast<dest>(s)</tt> will return @c s --
  108.  * presuming that @c source can be converted to @c dest by the normal rules of
  109.  * C++.
  110.  *
  111.  * By default, <tt>ll_template_cast<dest>(s)</tt> will return 0 unless @c s's
  112.  * type is literally identical to @c dest. (This is because of the
  113.  * straightforward application of template specialization rules.) That can
  114.  * lead to surprising results, e.g.:
  115.  *
  116.  * @code
  117.  * Foo myFoo;
  118.  * const Foo* fooptr = ll_template_cast<const Foo*>(&myFoo);
  119.  * @endcode
  120.  *
  121.  * Here @c fooptr will be 0 because <tt>&myFoo</tt> is of type <tt>Foo*</tt>
  122.  * -- @em not <tt>const Foo*</tt>. (Declaring <tt>const Foo myFoo;</tt> would
  123.  * force the compiler to do the right thing.)
  124.  *
  125.  * More disappointingly:
  126.  * @code
  127.  * struct Base {};
  128.  * struct Subclass: public Base {};
  129.  * Subclass object;
  130.  * Base* ptr = ll_template_cast<Base*>(&object);
  131.  * @endcode
  132.  *
  133.  * Here @c ptr will be 0 because <tt>&object</tt> is of type
  134.  * <tt>Subclass*</tt> rather than <tt>Base*</tt>. We @em want this cast to
  135.  * succeed, but without our help ll_template_cast can't recognize it.
  136.  *
  137.  * The following would suffice:
  138.  * @code
  139.  * LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
  140.  * ...
  141.  * Base* ptr = ll_template_cast<Base*>(&object);
  142.  * @endcode
  143.  *
  144.  * However, as noted earlier, this is easily fooled:
  145.  * @code
  146.  * const Base* ptr = ll_template_cast<const Base*>(&object);
  147.  * @endcode
  148.  * would still produce 0 because we haven't yet seen:
  149.  * @code
  150.  * LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
  151.  * @endcode
  152.  *
  153.  * @TODO
  154.  * This macro should use Boost type_traits facilities for stripping and
  155.  * re-adding @c const and @c volatile qualifiers so that invoking
  156.  * LL_TEMPLATE_CONVERTIBLE(dest, source) will automatically generate all
  157.  * permitted permutations. It's really not fair to the coder to require
  158.  * separate:
  159.  * @code
  160.  * LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
  161.  * LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
  162.  * LL_TEMPLATE_CONVERTIBLE(const Base*, const Subclass*);
  163.  * @endcode
  164.  *
  165.  * (Naturally we omit <tt>LL_TEMPLATE_CONVERTIBLE(Base*, const Subclass*)</tt>
  166.  * because that's not permitted by normal C++ assignment anyway.)
  167.  */
  168. #define LL_TEMPLATE_CONVERTIBLE(DEST, SOURCE)   
  169. template <>                                     
  170. struct ll_template_cast_impl<DEST, SOURCE>      
  171. {                                               
  172.     DEST operator()(SOURCE wrapper)             
  173.     {                                           
  174.         return wrapper;                         
  175.     }                                           
  176. }
  177. #endif /* ! defined(LL_LL_TEMPLATE_CAST_H) */