6f76c8cd0cc6e795c4e15089ffc543a7ba50dbd6
[WebKit-https.git] / Source / WTF / wtf / TypeCasts.h
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef TypeCasts_h
27 #define TypeCasts_h
28
29 #include <type_traits>
30
31 namespace WTF {
32
33 template <typename ExpectedType, typename ArgType>
34 struct TypeCastTraits {
35     static bool isOfType(ArgType&)
36     {
37         // If you're hitting this assertion, it is likely because you used
38         // is<>() or downcast<>() with a type that doesn't have the needed
39         // TypeCastTraits specialization. Please use the following macro
40         // to add that specialization:
41         // SPECIALIZE_TYPE_TRAITS_BEGIN() / SPECIALIZE_TYPE_TRAITS_END()
42         static_assert(std::is_void<ExpectedType>::value, "Missing TypeCastTraits specialization");
43         return false;
44     }
45 };
46
47 template <typename ExpectedType>
48 struct TypeCastTraits<ExpectedType, ExpectedType> {
49     static bool isOfType(ExpectedType&) { return true; }
50 };
51
52 // Type checking function, to use before casting with downcast<>().
53 template <typename ExpectedType, typename ArgType>
54 inline bool is(ArgType& source)
55 {
56     static_assert(!std::is_base_of<ExpectedType, ArgType>::value, "Unnecessary type check");
57     return TypeCastTraits<const ExpectedType, const ArgType>::isOfType(source);
58 }
59
60 template <typename ExpectedType, typename ArgType>
61 inline bool is(ArgType* source)
62 {
63     ASSERT(source);
64     static_assert(!std::is_base_of<ExpectedType, ArgType>::value, "Unnecessary type check");
65     return TypeCastTraits<const ExpectedType, const ArgType>::isOfType(*source);
66 }
67
68 // Safe downcasting functions.
69 template<typename Target, typename Source>
70 inline typename std::conditional<std::is_const<Source>::value, const Target&, Target&>::type downcast(Source& source)
71 {
72     static_assert(!std::is_base_of<Target, Source>::value, "Unnecessary cast");
73     ASSERT_WITH_SECURITY_IMPLICATION(is<Target>(source));
74     return static_cast<typename std::conditional<std::is_const<Source>::value, const Target&, Target&>::type>(source);
75 }
76 template<typename Target, typename Source> inline typename std::conditional<std::is_const<Source>::value, const Target*, Target*>::type downcast(Source* source)
77 {
78     static_assert(!std::is_base_of<Target, Source>::value, "Unnecessary cast");
79     ASSERT_WITH_SECURITY_IMPLICATION(!source || is<Target>(*source));
80     return static_cast<typename std::conditional<std::is_const<Source>::value, const Target*, Target*>::type>(source);
81 }
82
83 // Add support for type checking / casting using is<>() / downcast<>() helpers for a specific class.
84 #define SPECIALIZE_TYPE_TRAITS_BEGIN(ClassName) \
85 namespace WTF { \
86 template <typename ArgType> \
87 class TypeCastTraits<const ClassName, ArgType> { \
88 public: \
89     static bool isOfType(ArgType& source) { return isType(source); } \
90 private:
91
92 #define SPECIALIZE_TYPE_TRAITS_END() \
93 }; \
94 }
95
96 } // namespace WTF
97
98 using WTF::is;
99 using WTF::downcast;
100
101 #endif // TypeCasts_h