1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2014 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 #ifndef GOOGLE_PROTOBUF_CASTS_H__
32 #define GOOGLE_PROTOBUF_CASTS_H__
33
34 #include <type_traits>
35
36 #include <google/protobuf/stubs/common.h>
37
38 namespace google {
39 namespace protobuf {
40 namespace internal {
41 // Use implicit_cast as a safe version of static_cast or const_cast
42 // for upcasting in the type hierarchy (i.e. casting a pointer to Foo
43 // to a pointer to SuperclassOfFoo or casting a pointer to Foo to
44 // a const pointer to Foo).
45 // When you use implicit_cast, the compiler checks that the cast is safe.
46 // Such explicit implicit_casts are necessary in surprisingly many
47 // situations where C++ demands an exact type match instead of an
48 // argument type convertable to a target type.
49 //
50 // The From type can be inferred, so the preferred syntax for using
51 // implicit_cast is the same as for static_cast etc.:
52 //
53 // implicit_cast<ToType>(expr)
54 //
55 // implicit_cast would have been part of the C++ standard library,
56 // but the proposal was submitted too late. It will probably make
57 // its way into the language in the future.
58 template<typename To, typename From>
implicit_cast(From const & f)59 inline To implicit_cast(From const &f) {
60 return f;
61 }
62
63 // When you upcast (that is, cast a pointer from type Foo to type
64 // SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
65 // always succeed. When you downcast (that is, cast a pointer from
66 // type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
67 // how do you know the pointer is really of type SubclassOfFoo? It
68 // could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
69 // when you downcast, you should use this macro. In debug mode, we
70 // use dynamic_cast<> to double-check the downcast is legal (we die
71 // if it's not). In normal mode, we do the efficient static_cast<>
72 // instead. Thus, it's important to test in debug mode to make sure
73 // the cast is legal!
74 // This is the only place in the code we should use dynamic_cast<>.
75 // In particular, you SHOULDN'T be using dynamic_cast<> in order to
76 // do RTTI (eg code like this:
77 // if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
78 // if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
79 // You should design the code some other way not to need this.
80
81 template<typename To, typename From> // use like this: down_cast<T*>(foo);
down_cast(From * f)82 inline To down_cast(From* f) { // so we only accept pointers
83 // Ensures that To is a sub-type of From *. This test is here only
84 // for compile-time type checking, and has no overhead in an
85 // optimized build at run-time, as it will be optimized away
86 // completely.
87 if (false) {
88 implicit_cast<From*, To>(0);
89 }
90
91 #if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
92 assert(f == nullptr || dynamic_cast<To>(f) != nullptr); // RTTI: debug mode only!
93 #endif
94 return static_cast<To>(f);
95 }
96
97 template<typename To, typename From> // use like this: down_cast<T&>(foo);
down_cast(From & f)98 inline To down_cast(From& f) {
99 typedef typename std::remove_reference<To>::type* ToAsPointer;
100 // Ensures that To is a sub-type of From *. This test is here only
101 // for compile-time type checking, and has no overhead in an
102 // optimized build at run-time, as it will be optimized away
103 // completely.
104 if (false) {
105 implicit_cast<From*, ToAsPointer>(0);
106 }
107
108 #if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
109 // RTTI: debug mode only!
110 assert(dynamic_cast<ToAsPointer>(&f) != nullptr);
111 #endif
112 return *static_cast<ToAsPointer>(&f);
113 }
114
115 template<typename To, typename From>
bit_cast(const From & from)116 inline To bit_cast(const From& from) {
117 GOOGLE_COMPILE_ASSERT(sizeof(From) == sizeof(To),
118 bit_cast_with_different_sizes);
119 To dest;
120 memcpy(&dest, &from, sizeof(dest));
121 return dest;
122 }
123
124 } // namespace internal
125
126 // We made these internal so that they would show up as such in the docs,
127 // but we don't want to stick "internal::" in front of them everywhere.
128 using internal::implicit_cast;
129 using internal::down_cast;
130 using internal::bit_cast;
131
132 } // namespace protobuf
133 } // namespace google
134 #endif // GOOGLE_PROTOBUF_CASTS_H__
135