Line data Source code
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 8879 : 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__
|