/* * Copyright (C) 2014 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TypeCasts_h #define TypeCasts_h #include namespace WTF { template ::value> struct TypeCastTraits { static bool isOfType(ArgType&) { // If you're hitting this assertion, it is likely because you used // is<>() or downcast<>() with a type that doesn't have the needed // TypeCastTraits specialization. Please use the following macro // to add that specialization: // SPECIALIZE_TYPE_TRAITS_BEGIN() / SPECIALIZE_TYPE_TRAITS_END() static_assert(std::is_void::value, "Missing TypeCastTraits specialization"); return false; } }; // Template specialization for the case where ExpectedType is a base of ArgType, // so we can return return true unconditionally. template struct TypeCastTraits { static bool isOfType(ArgType&) { return true; } }; // Type checking function, to use before casting with downcast<>(). template inline bool is(ArgType& source) { static_assert(std::is_base_of::value, "Unnecessary type check"); return TypeCastTraits::isOfType(source); } template inline bool is(ArgType* source) { static_assert(std::is_base_of::value, "Unnecessary type check"); return source && TypeCastTraits::isOfType(*source); } // Update T's constness to match Reference's. template struct match_constness { typedef typename std::conditional::value, typename std::add_const::type, typename std::remove_const::type>::type type; }; // Safe downcasting functions. template inline typename match_constness::type& downcast(Source& source) { static_assert(!std::is_same::value, "Unnecessary cast to same type"); static_assert(std::is_base_of::value, "Should be a downcast"); ASSERT_WITH_SECURITY_IMPLICATION(is(source)); return static_cast::type&>(source); } template inline typename match_constness::type* downcast(Source* source) { static_assert(!std::is_same::value, "Unnecessary cast to same type"); static_assert(std::is_base_of::value, "Should be a downcast"); ASSERT_WITH_SECURITY_IMPLICATION(!source || is(*source)); return static_cast::type*>(source); } // Add support for type checking / casting using is<>() / downcast<>() helpers for a specific class. #define SPECIALIZE_TYPE_TRAITS_BEGIN(ClassName) \ namespace WTF { \ template \ class TypeCastTraits { \ public: \ static bool isOfType(ArgType& source) { return isType(source); } \ private: #define SPECIALIZE_TYPE_TRAITS_END() \ }; \ } } // namespace WTF using WTF::TypeCastTraits; using WTF::is; using WTF::downcast; #endif // TypeCasts_h