• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <google/protobuf/stubs/common.h>
35 
36 #include <google/protobuf/port_def.inc>
37 #include <type_traits>
38 
39 namespace google {
40 namespace protobuf {
41 namespace internal {
42 
43 // Use implicit_cast as a safe version of static_cast or const_cast
44 // for upcasting in the type hierarchy (i.e. casting a pointer to Foo
45 // to a pointer to SuperclassOfFoo or casting a pointer to Foo to
46 // a const pointer to Foo).
47 // When you use implicit_cast, the compiler checks that the cast is safe.
48 // Such explicit implicit_casts are necessary in surprisingly many
49 // situations where C++ demands an exact type match instead of an
50 // argument type convertable to a target type.
51 //
52 // The From type can be inferred, so the preferred syntax for using
53 // implicit_cast is the same as for static_cast etc.:
54 //
55 //   implicit_cast<ToType>(expr)
56 //
57 // implicit_cast would have been part of the C++ standard library,
58 // but the proposal was submitted too late.  It will probably make
59 // its way into the language in the future.
60 template<typename To, typename From>
implicit_cast(From const & f)61 inline To implicit_cast(From const &f) {
62   return f;
63 }
64 
65 // When you upcast (that is, cast a pointer from type Foo to type
66 // SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
67 // always succeed.  When you downcast (that is, cast a pointer from
68 // type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
69 // how do you know the pointer is really of type SubclassOfFoo?  It
70 // could be a bare Foo, or of type DifferentSubclassOfFoo.  Thus,
71 // when you downcast, you should use this macro.  In debug mode, we
72 // use dynamic_cast<> to double-check the downcast is legal (we die
73 // if it's not).  In normal mode, we do the efficient static_cast<>
74 // instead.  Thus, it's important to test in debug mode to make sure
75 // the cast is legal!
76 //    This is the only place in the code we should use dynamic_cast<>.
77 // In particular, you SHOULDN'T be using dynamic_cast<> in order to
78 // do RTTI (eg code like this:
79 //    if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
80 //    if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
81 // You should design the code some other way not to need this.
82 
83 template<typename To, typename From>     // use like this: down_cast<T*>(foo);
down_cast(From * f)84 inline To down_cast(From* f) {                   // so we only accept pointers
85   // Ensures that To is a sub-type of From *.  This test is here only
86   // for compile-time type checking, and has no overhead in an
87   // optimized build at run-time, as it will be optimized away
88   // completely.
89   if (false) {
90     implicit_cast<From*, To>(0);
91   }
92 
93 #if !defined(NDEBUG) && PROTOBUF_RTTI
94   assert(f == nullptr || dynamic_cast<To>(f) != nullptr);  // RTTI: debug mode only!
95 #endif
96   return static_cast<To>(f);
97 }
98 
99 template<typename To, typename From>    // use like this: down_cast<T&>(foo);
down_cast(From & f)100 inline To down_cast(From& f) {
101   typedef typename std::remove_reference<To>::type* ToAsPointer;
102   // Ensures that To is a sub-type of From *.  This test is here only
103   // for compile-time type checking, and has no overhead in an
104   // optimized build at run-time, as it will be optimized away
105   // completely.
106   if (false) {
107     implicit_cast<From*, ToAsPointer>(0);
108   }
109 
110 #if !defined(NDEBUG) && PROTOBUF_RTTI
111   // RTTI: debug mode only!
112   assert(dynamic_cast<ToAsPointer>(&f) != nullptr);
113 #endif
114   return *static_cast<ToAsPointer>(&f);
115 }
116 
117 template<typename To, typename From>
bit_cast(const From & from)118 inline To bit_cast(const From& from) {
119   GOOGLE_COMPILE_ASSERT(sizeof(From) == sizeof(To),
120                         bit_cast_with_different_sizes);
121   To dest;
122   memcpy(&dest, &from, sizeof(dest));
123   return dest;
124 }
125 
126 }  // namespace internal
127 
128 // We made these internal so that they would show up as such in the docs,
129 // but we don't want to stick "internal::" in front of them everywhere.
130 using internal::implicit_cast;
131 using internal::down_cast;
132 using internal::bit_cast;
133 
134 }  // namespace protobuf
135 }  // namespace google
136 
137 #include <google/protobuf/port_undef.inc>
138 
139 #endif  // GOOGLE_PROTOBUF_CASTS_H__
140