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