Most in particular llevents.h, which comes along with the demand that the old events in llevent.h are put in a namespace LLOldEvents. Made all changes necessary to compile the rest of the code again (without changing the actual code: it's still using the old events). This patch also removes LLStopWhenHandled and LLStandardSignal from indra/llui/llnotifications.h because those are moved to llevents.h. That seems to be the only change to indra/llui/llnotifications.h that isn't floater related, so I left the rest of that file alone.
178 lines
5.5 KiB
C++
178 lines
5.5 KiB
C++
/**
|
|
* @file ll_template_cast.h
|
|
* @author Nat Goodspeed
|
|
* @date 2009-11-21
|
|
* @brief Define ll_template_cast function
|
|
*
|
|
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2010, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#if ! defined(LL_LL_TEMPLATE_CAST_H)
|
|
#define LL_LL_TEMPLATE_CAST_H
|
|
|
|
/**
|
|
* Implementation for ll_template_cast() (q.v.).
|
|
*
|
|
* Default implementation: trying to cast two completely unrelated types
|
|
* returns 0. Typically you'd specify T and U as pointer types, but in fact T
|
|
* can be any type that can be initialized with 0.
|
|
*/
|
|
template <typename T, typename U>
|
|
struct ll_template_cast_impl
|
|
{
|
|
T operator()(U)
|
|
{
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* ll_template_cast<T>(some_value) is for use in a template function when
|
|
* some_value might be of arbitrary type, but you want to recognize type T
|
|
* specially.
|
|
*
|
|
* It's designed for use with pointer types. Example:
|
|
* @code
|
|
* struct SpecialClass
|
|
* {
|
|
* void someMethod(const std::string&) const;
|
|
* };
|
|
*
|
|
* template <class REALCLASS>
|
|
* void somefunc(const REALCLASS& instance)
|
|
* {
|
|
* const SpecialClass* ptr = ll_template_cast<const SpecialClass*>(&instance);
|
|
* if (ptr)
|
|
* {
|
|
* ptr->someMethod("Call method only available on SpecialClass");
|
|
* }
|
|
* }
|
|
* @endcode
|
|
*
|
|
* Why is this better than dynamic_cast<>? Because unless OtherClass is
|
|
* polymorphic, the following won't even compile (gcc 4.0.1):
|
|
* @code
|
|
* OtherClass other;
|
|
* SpecialClass* ptr = dynamic_cast<SpecialClass*>(&other);
|
|
* @endcode
|
|
* to say nothing of this:
|
|
* @code
|
|
* void function(int);
|
|
* SpecialClass* ptr = dynamic_cast<SpecialClass*>(&function);
|
|
* @endcode
|
|
* ll_template_cast handles these kinds of cases by returning 0.
|
|
*/
|
|
template <typename T, typename U>
|
|
T ll_template_cast(U value)
|
|
{
|
|
return ll_template_cast_impl<T, U>()(value);
|
|
}
|
|
|
|
/**
|
|
* Implementation for ll_template_cast() (q.v.).
|
|
*
|
|
* Implementation for identical types: return same value.
|
|
*/
|
|
template <typename T>
|
|
struct ll_template_cast_impl<T, T>
|
|
{
|
|
T operator()(T value)
|
|
{
|
|
return value;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* LL_TEMPLATE_CONVERTIBLE(dest, source) asserts that, for a value @c s of
|
|
* type @c source, <tt>ll_template_cast<dest>(s)</tt> will return @c s --
|
|
* presuming that @c source can be converted to @c dest by the normal rules of
|
|
* C++.
|
|
*
|
|
* By default, <tt>ll_template_cast<dest>(s)</tt> will return 0 unless @c s's
|
|
* type is literally identical to @c dest. (This is because of the
|
|
* straightforward application of template specialization rules.) That can
|
|
* lead to surprising results, e.g.:
|
|
*
|
|
* @code
|
|
* Foo myFoo;
|
|
* const Foo* fooptr = ll_template_cast<const Foo*>(&myFoo);
|
|
* @endcode
|
|
*
|
|
* Here @c fooptr will be 0 because <tt>&myFoo</tt> is of type <tt>Foo*</tt>
|
|
* -- @em not <tt>const Foo*</tt>. (Declaring <tt>const Foo myFoo;</tt> would
|
|
* force the compiler to do the right thing.)
|
|
*
|
|
* More disappointingly:
|
|
* @code
|
|
* struct Base {};
|
|
* struct Subclass: public Base {};
|
|
* Subclass object;
|
|
* Base* ptr = ll_template_cast<Base*>(&object);
|
|
* @endcode
|
|
*
|
|
* Here @c ptr will be 0 because <tt>&object</tt> is of type
|
|
* <tt>Subclass*</tt> rather than <tt>Base*</tt>. We @em want this cast to
|
|
* succeed, but without our help ll_template_cast can't recognize it.
|
|
*
|
|
* The following would suffice:
|
|
* @code
|
|
* LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
|
|
* ...
|
|
* Base* ptr = ll_template_cast<Base*>(&object);
|
|
* @endcode
|
|
*
|
|
* However, as noted earlier, this is easily fooled:
|
|
* @code
|
|
* const Base* ptr = ll_template_cast<const Base*>(&object);
|
|
* @endcode
|
|
* would still produce 0 because we haven't yet seen:
|
|
* @code
|
|
* LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
|
|
* @endcode
|
|
*
|
|
* @TODO
|
|
* This macro should use Boost type_traits facilities for stripping and
|
|
* re-adding @c const and @c volatile qualifiers so that invoking
|
|
* LL_TEMPLATE_CONVERTIBLE(dest, source) will automatically generate all
|
|
* permitted permutations. It's really not fair to the coder to require
|
|
* separate:
|
|
* @code
|
|
* LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
|
|
* LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
|
|
* LL_TEMPLATE_CONVERTIBLE(const Base*, const Subclass*);
|
|
* @endcode
|
|
*
|
|
* (Naturally we omit <tt>LL_TEMPLATE_CONVERTIBLE(Base*, const Subclass*)</tt>
|
|
* because that's not permitted by normal C++ assignment anyway.)
|
|
*/
|
|
#define LL_TEMPLATE_CONVERTIBLE(DEST, SOURCE) \
|
|
template <> \
|
|
struct ll_template_cast_impl<DEST, SOURCE> \
|
|
{ \
|
|
DEST operator()(SOURCE wrapper) \
|
|
{ \
|
|
return wrapper; \
|
|
} \
|
|
}
|
|
|
|
#endif /* ! defined(LL_LL_TEMPLATE_CAST_H) */
|