1// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef BASE_CASTS_H_ 6#define BASE_CASTS_H_ 7 8#include <assert.h> // for use with down_cast<> 9#include <string.h> // for memcpy 10 11#include "base/macros.h" 12 13 14// Use implicit_cast as a safe version of static_cast or const_cast 15// for upcasting in the type hierarchy (i.e. casting a pointer to Foo 16// to a pointer to SuperclassOfFoo or casting a pointer to Foo to 17// a const pointer to Foo). 18// When you use implicit_cast, the compiler checks that the cast is safe. 19// Such explicit implicit_casts are necessary in surprisingly many 20// situations where C++ demands an exact type match instead of an 21// argument type convertable to a target type. 22// 23// The From type can be inferred, so the preferred syntax for using 24// implicit_cast is the same as for static_cast etc.: 25// 26// implicit_cast<ToType>(expr) 27// 28// implicit_cast would have been part of the C++ standard library, 29// but the proposal was submitted too late. It will probably make 30// its way into the language in the future. 31template<typename To, typename From> 32inline To implicit_cast(From const &f) { 33 return f; 34} 35 36 37// When you upcast (that is, cast a pointer from type Foo to type 38// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts 39// always succeed. When you downcast (that is, cast a pointer from 40// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because 41// how do you know the pointer is really of type SubclassOfFoo? It 42// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, 43// when you downcast, you should use this macro. In debug mode, we 44// use dynamic_cast<> to double-check the downcast is legal (we die 45// if it's not). In normal mode, we do the efficient static_cast<> 46// instead. Thus, it's important to test in debug mode to make sure 47// the cast is legal! 48// This is the only place in the code we should use dynamic_cast<>. 49// In particular, you SHOULDN'T be using dynamic_cast<> in order to 50// do RTTI (eg code like this: 51// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo); 52// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo); 53// You should design the code some other way not to need this. 54 55template<typename To, typename From> // use like this: down_cast<T*>(foo); 56inline To down_cast(From* f) { // so we only accept pointers 57 // Ensures that To is a sub-type of From *. This test is here only 58 // for compile-time type checking, and has no overhead in an 59 // optimized build at run-time, as it will be optimized away 60 // completely. 61 if (false) { 62 implicit_cast<From*, To>(0); 63 } 64 65 assert(f == NULL || dynamic_cast<To>(f) != NULL); // RTTI: debug mode only! 66 return static_cast<To>(f); 67} 68 69// Overload of down_cast for references. Use like this: down_cast<T&>(foo). 70// The code is slightly convoluted because we're still using the pointer 71// form of dynamic cast. (The reference form throws an exception if it 72// fails.) 73// 74// There's no need for a special const overload either for the pointer 75// or the reference form. If you call down_cast with a const T&, the 76// compiler will just bind From to const T. 77template<typename To, typename From> 78inline To down_cast(From& f) { 79 COMPILE_ASSERT(base::is_reference<To>::value, target_type_not_a_reference); 80 typedef typename base::remove_reference<To>::type* ToAsPointer; 81 if (false) { 82 // Compile-time check that To inherits from From. See above for details. 83 implicit_cast<From*, ToAsPointer>(0); 84 } 85 86 assert(dynamic_cast<ToAsPointer>(&f) != NULL); // RTTI: debug mode only 87 return static_cast<To>(f); 88} 89 90// bit_cast<Dest,Source> is a template function that implements the 91// equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in 92// very low-level functions like the protobuf library and fast math 93// support. 94// 95// float f = 3.14159265358979; 96// int i = bit_cast<int32>(f); 97// // i = 0x40490fdb 98// 99// The classical address-casting method is: 100// 101// // WRONG 102// float f = 3.14159265358979; // WRONG 103// int i = * reinterpret_cast<int*>(&f); // WRONG 104// 105// The address-casting method actually produces undefined behavior 106// according to ISO C++ specification section 3.10 -15 -. Roughly, this 107// section says: if an object in memory has one type, and a program 108// accesses it with a different type, then the result is undefined 109// behavior for most values of "different type". 110// 111// This is true for any cast syntax, either *(int*)&f or 112// *reinterpret_cast<int*>(&f). And it is particularly true for 113// conversions betweeen integral lvalues and floating-point lvalues. 114// 115// The purpose of 3.10 -15- is to allow optimizing compilers to assume 116// that expressions with different types refer to different memory. gcc 117// 4.0.1 has an optimizer that takes advantage of this. So a 118// non-conforming program quietly produces wildly incorrect output. 119// 120// The problem is not the use of reinterpret_cast. The problem is type 121// punning: holding an object in memory of one type and reading its bits 122// back using a different type. 123// 124// The C++ standard is more subtle and complex than this, but that 125// is the basic idea. 126// 127// Anyways ... 128// 129// bit_cast<> calls memcpy() which is blessed by the standard, 130// especially by the example in section 3.9 . Also, of course, 131// bit_cast<> wraps up the nasty logic in one place. 132// 133// Fortunately memcpy() is very fast. In optimized mode, with a 134// constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline 135// code with the minimal amount of data movement. On a 32-bit system, 136// memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8) 137// compiles to two loads and two stores. 138// 139// I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1. 140// 141// WARNING: if Dest or Source is a non-POD type, the result of the memcpy 142// is likely to surprise you. 143// 144 145template <class Dest, class Source> 146inline Dest bit_cast(const Source& source) { 147 // Compile time assertion: sizeof(Dest) == sizeof(Source) 148 // A compile error here means your Dest and Source have different sizes. 149 typedef char VerifySizesAreEqual [sizeof(Dest) == sizeof(Source) ? 1 : -1]; 150 151 Dest dest; 152 memcpy(&dest, &source, sizeof(dest)); 153 return dest; 154} 155 156#endif // BASE_CASTS_H_ 157