| // Copyright 2009 Google Inc. All Rights Reserved. |
| // |
| // Various Google-specific casting templates. |
| // |
| // This code is compiled directly on many platforms, including client |
| // platforms like Windows, Mac, and embedded systems. Before making |
| // any changes here, make sure that you're not breaking any platforms. |
| // |
| |
| #ifndef BASE_CASTS_H_ |
| #define BASE_CASTS_H_ |
| |
| #include <assert.h> // for use with down_cast<> |
| #include <string.h> // for memcpy |
| #include <limits.h> // for enumeration casts and tests |
| |
| #include <common/logging.h> |
| |
| #include "gutil/macros.h" |
| #include "gutil/template_util.h" |
| #include "gutil/type_traits.h" |
| |
| // Use implicit_cast as a safe version of static_cast or const_cast |
| // for implicit conversions. For example: |
| // - Upcasting in a type hierarchy. |
| // - Performing arithmetic conversions (int32 to int64, int to double, etc.). |
| // - Adding const or volatile qualifiers. |
| // |
| // In general, implicit_cast can be used to convert this code |
| // To to = from; |
| // DoSomething(to); |
| // to this |
| // DoSomething(implicit_cast<To>(from)); |
| // |
| // base::identity_ is used to make a non-deduced context, which |
| // forces all callers to explicitly specify the template argument. |
| template<typename To> |
| inline To implicit_cast(typename base::identity_<To>::type to) { |
| return to; |
| } |
| |
| // This version of implicit_cast is used when two template arguments |
| // are specified. It's obsolete and should not be used. |
| template<typename To, typename From> |
| inline To implicit_cast(typename base::identity_<From>::type const &f) { |
| return f; |
| } |
| |
| |
| // When you upcast (that is, cast a pointer from type Foo to type |
| // SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts |
| // always succeed. When you downcast (that is, cast a pointer from |
| // type Foo to type SubclassOfFoo), static_cast<> isn't safe, because |
| // how do you know the pointer is really of type SubclassOfFoo? It |
| // could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, |
| // when you downcast, you should use this macro. In debug mode, we |
| // use dynamic_cast<> to double-check the downcast is legal (we die |
| // if it's not). In normal mode, we do the efficient static_cast<> |
| // instead. Thus, it's important to test in debug mode to make sure |
| // the cast is legal! |
| // This is the only place in the code we should use dynamic_cast<>. |
| // In particular, you SHOULDN'T be using dynamic_cast<> in order to |
| // do RTTI (eg code like this: |
| // if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo); |
| // if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo); |
| // You should design the code some other way not to need this. |
| |
| template<typename To, typename From> // use like this: down_cast<T*>(foo); |
| inline To down_cast(From* f) { // so we only accept pointers |
| // Ensures that To is a sub-type of From *. This test is here only |
| // for compile-time type checking, and has no overhead in an |
| // optimized build at run-time, as it will be optimized away |
| // completely. |
| |
| // TODO(user): This should use COMPILE_ASSERT. |
| if (false) { |
| ::implicit_cast<From*, To>(NULL); |
| } |
| |
| // uses RTTI in dbg and fastbuild. asserts are disabled in opt builds. |
| assert(f == NULL || dynamic_cast<To>(f) != NULL); |
| return static_cast<To>(f); |
| } |
| |
| // Overload of down_cast for references. Use like this: down_cast<T&>(foo). |
| // The code is slightly convoluted because we're still using the pointer |
| // form of dynamic cast. (The reference form throws an exception if it |
| // fails.) |
| // |
| // There's no need for a special const overload either for the pointer |
| // or the reference form. If you call down_cast with a const T&, the |
| // compiler will just bind From to const T. |
| template<typename To, typename From> |
| inline To down_cast(From& f) { |
| COMPILE_ASSERT(base::is_reference<To>::value, target_type_not_a_reference); |
| typedef typename base::remove_reference<To>::type* ToAsPointer; |
| if (false) { |
| // Compile-time check that To inherits from From. See above for details. |
| ::implicit_cast<From*, ToAsPointer>(NULL); |
| } |
| |
| assert(dynamic_cast<ToAsPointer>(&f) != NULL); // RTTI: debug mode only |
| return static_cast<To>(f); |
| } |
| |
| // bit_cast<Dest,Source> is a template function that implements the |
| // equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in |
| // very low-level functions like the protobuf library and fast math |
| // support. |
| // |
| // float f = 3.14159265358979; |
| // int i = bit_cast<int32>(f); |
| // // i = 0x40490fdb |
| // |
| // The classical address-casting method is: |
| // |
| // // WRONG |
| // float f = 3.14159265358979; // WRONG |
| // int i = * reinterpret_cast<int*>(&f); // WRONG |
| // |
| // The address-casting method actually produces undefined behavior |
| // according to ISO C++ specification section 3.10 -15 -. Roughly, this |
| // section says: if an object in memory has one type, and a program |
| // accesses it with a different type, then the result is undefined |
| // behavior for most values of "different type". |
| // |
| // This is true for any cast syntax, either *(int*)&f or |
| // *reinterpret_cast<int*>(&f). And it is particularly true for |
| // conversions betweeen integral lvalues and floating-point lvalues. |
| // |
| // The purpose of 3.10 -15- is to allow optimizing compilers to assume |
| // that expressions with different types refer to different memory. gcc |
| // 4.0.1 has an optimizer that takes advantage of this. So a |
| // non-conforming program quietly produces wildly incorrect output. |
| // |
| // The problem is not the use of reinterpret_cast. The problem is type |
| // punning: holding an object in memory of one type and reading its bits |
| // back using a different type. |
| // |
| // The C++ standard is more subtle and complex than this, but that |
| // is the basic idea. |
| // |
| // Anyways ... |
| // |
| // bit_cast<> calls memcpy() which is blessed by the standard, |
| // especially by the example in section 3.9 . Also, of course, |
| // bit_cast<> wraps up the nasty logic in one place. |
| // |
| // Fortunately memcpy() is very fast. In optimized mode, with a |
| // constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline |
| // code with the minimal amount of data movement. On a 32-bit system, |
| // memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8) |
| // compiles to two loads and two stores. |
| // |
| // I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1. |
| // |
| // WARNING: if Dest or Source is a non-POD type, the result of the memcpy |
| // is likely to surprise you. |
| // |
| // Props to Bill Gibbons for the compile time assertion technique and |
| // Art Komninos and Igor Tandetnik for the msvc experiments. |
| // |
| // -- mec 2005-10-17 |
| |
| template <class Dest, class Source> |
| inline Dest bit_cast(const Source& source) { |
| // Compile time assertion: sizeof(Dest) == sizeof(Source) |
| // A compile error here means your Dest and Source have different sizes. |
| COMPILE_ASSERT(sizeof(Dest) == sizeof(Source), VerifySizesAreEqual); |
| |
| Dest dest; |
| memcpy(&dest, &source, sizeof(dest)); |
| return dest; |
| } |
| |
| |
| // **** Enumeration Casts and Tests |
| // |
| // C++ requires that the value of an integer that is converted to an |
| // enumeration be within the value bounds of the enumeration. Modern |
| // compilers can and do take advantage of this requirement to optimize |
| // programs. So, using a raw static_cast with enums can be bad. See |
| // |
| // The following templates and macros enable casting from an int to an enum |
| // with checking against the appropriate bounds. First, when defining an |
| // enumeration, identify the limits of the values of its enumerators. |
| // |
| // enum A { A_min = -18, A_max = 33 }; |
| // MAKE_ENUM_LIMITS(A, A_min, A_max) |
| // |
| // Convert an enum to an int in one of two ways. The prefered way is a |
| // tight conversion, which ensures that A_min <= value <= A_max. |
| // |
| // A var = tight_enum_cast<A>(3); |
| // |
| // However, the C++ language defines the set of possible values for an |
| // enumeration to be essentially the range of a bitfield that can represent |
| // all the enumerators, i.e. those within the nearest containing power |
| // of two. In the example above, the nearest positive power of two is 64, |
| // and so the upper bound is 63. The nearest negative power of two is |
| // -32 and so the lower bound is -32 (two's complement), which is upgraded |
| // to match the upper bound, becoming -64. The values within this range |
| // of -64 to 63 are valid, according to the C++ standard. You can cast |
| // values within this range as follows. |
| // |
| // A var = loose_enum_cast<A>(45); |
| // |
| // These casts will log a message if the value does not reside within the |
| // specified range, and will be fatal when in debug mode. |
| // |
| // For those times when an assert too strong, there are test functions. |
| // |
| // bool var = tight_enum_test<A>(3); |
| // bool var = loose_enum_test<A>(45); |
| // |
| // For code that needs to use the enumeration value if and only if |
| // it is good, there is a function that both tests and casts. |
| // |
| // int i = ....; |
| // A var; |
| // if (tight_enum_test_cast<A>(i, &var)) |
| // .... // use valid var with value as indicated by i |
| // else |
| // .... // handle invalid enum cast |
| // |
| // The enum test/cast facility is currently limited to enumerations that |
| // fit within an int. It is also limited to two's complement ints. |
| |
| // ** Implementation Description |
| // |
| // The enum_limits template class captures the minimum and maximum |
| // enumerator. All uses of this template are intended to be of |
| // specializations, so the generic has a field to identify itself as |
| // not specialized. The test/cast templates assert specialization. |
| |
| template <typename Enum> |
| class enum_limits { |
| public: |
| static const Enum min_enumerator = 0; |
| static const Enum max_enumerator = 0; |
| static const bool is_specialized = false; |
| }; |
| |
| // Now we define the macro to define the specialization for enum_limits. |
| // The specialization checks that the enumerators fit within an int. |
| // This checking relies on integral promotion. |
| |
| #define MAKE_ENUM_LIMITS(ENUM_TYPE, ENUM_MIN, ENUM_MAX) \ |
| template <> \ |
| class enum_limits<ENUM_TYPE> { \ |
| public: \ |
| static const ENUM_TYPE min_enumerator = ENUM_MIN; \ |
| static const ENUM_TYPE max_enumerator = ENUM_MAX; \ |
| static const bool is_specialized = true; \ |
| COMPILE_ASSERT(ENUM_MIN >= INT_MIN, enumerator_too_negative_for_int); \ |
| COMPILE_ASSERT(ENUM_MAX <= INT_MAX, enumerator_too_positive_for_int); \ |
| }; |
| |
| // The loose enum test/cast is actually the more complicated one, |
| // because of the problem of finding the bounds. |
| // |
| // The unary upper bound, ub, on a positive number is its positive |
| // saturation, i.e. for a value v within pow(2,k-1) <= v < pow(2,k), |
| // the upper bound is pow(2,k)-1. |
| // |
| // The unary lower bound, lb, on a negative number is its negative |
| // saturation, i.e. for a value v within -pow(2,k) <= v < -pow(2,k-1), |
| // the lower bound is -pow(2,k). |
| // |
| // The actual bounds are (1) the binary upper bound over the maximum |
| // enumerator and the one's complement of a negative minimum enumerator |
| // and (2) the binary lower bound over the minimum enumerator and the |
| // one's complement of the positive maximum enumerator, except that if no |
| // enumerators are negative, the lower bound is zero. |
| // |
| // The algorithm relies heavily on the observation that |
| // |
| // a,b>0 then ub(a,b) == ub(a) | ub(b) == ub(a|b) |
| // a,b<0 then lb(a,b) == lb(a) & lb(b) == lb(a&b) |
| // |
| // Note that the compiler will boil most of this code away |
| // because of value propagation on the constant enumerator bounds. |
| |
| template <typename Enum> |
| inline bool loose_enum_test(int e_val) { |
| COMPILE_ASSERT(enum_limits<Enum>::is_specialized, missing_MAKE_ENUM_LIMITS); |
| const Enum e_min = enum_limits<Enum>::min_enumerator; |
| const Enum e_max = enum_limits<Enum>::max_enumerator; |
| COMPILE_ASSERT(sizeof(e_val) == 4 || sizeof(e_val) == 8, unexpected_int_size); |
| |
| // Find the unary bounding negative number of e_min and e_max. |
| |
| // Find the unary bounding negative number of e_max. |
| // This would be b_min = e_max < 0 ? e_max : ~e_max, |
| // but we want to avoid branches to help the compiler. |
| int e_max_sign = e_max >> (sizeof(e_val)*8 - 1); |
| int b_min = ~e_max_sign ^ e_max; |
| |
| // Find the binary bounding negative of both e_min and e_max. |
| b_min &= e_min; |
| |
| // However, if e_min is postive, the result will be positive. |
| // Now clear all bits right of the most significant clear bit, |
| // which is a negative saturation for negative numbers. |
| // In the case of positive numbers, this is flush to zero. |
| b_min &= b_min >> 1; |
| b_min &= b_min >> 2; |
| b_min &= b_min >> 4; |
| b_min &= b_min >> 8; |
| b_min &= b_min >> 16; |
| #if INT_MAX > 2147483647 |
| b_min &= b_min >> 32; |
| #endif |
| |
| // Find the unary bounding positive number of e_max. |
| int b_max = e_max_sign ^ e_max; |
| |
| // Find the binary bounding postive number of that |
| // and the unary bounding positive number of e_min. |
| int e_min_sign = e_min >> (sizeof(e_val)*8 - 1); |
| b_max |= e_min_sign ^ e_min; |
| |
| // Now set all bits right of the most significant set bit, |
| // which is a postive saturation for positive numbers. |
| b_max |= b_max >> 1; |
| b_max |= b_max >> 2; |
| b_max |= b_max >> 4; |
| b_max |= b_max >> 8; |
| b_max |= b_max >> 16; |
| #if INT_MAX > 2147483647 |
| b_max |= b_max >> 32; |
| #endif |
| |
| // Finally test the bounds. |
| return b_min <= e_val && e_val <= b_max; |
| } |
| |
| template <typename Enum> |
| inline bool tight_enum_test(int e_val) { |
| COMPILE_ASSERT(enum_limits<Enum>::is_specialized, missing_MAKE_ENUM_LIMITS); |
| const Enum e_min = enum_limits<Enum>::min_enumerator; |
| const Enum e_max = enum_limits<Enum>::max_enumerator; |
| return e_min <= e_val && e_val <= e_max; |
| } |
| |
| template <typename Enum> |
| inline bool loose_enum_test_cast(int e_val, Enum* e_var) { |
| if (loose_enum_test<Enum>(e_val)) { |
| *e_var = static_cast<Enum>(e_val); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| template <typename Enum> |
| inline bool tight_enum_test_cast(int e_val, Enum* e_var) { |
| if (tight_enum_test<Enum>(e_val)) { |
| *e_var = static_cast<Enum>(e_val); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| namespace base { |
| namespace internal { |
| |
| inline void WarnEnumCastError(int value_of_int) { |
| LOG(DFATAL) << "Bad enum value " << value_of_int; |
| } |
| |
| } // namespace internal |
| } // namespace base |
| |
| template <typename Enum> |
| inline Enum loose_enum_cast(int e_val) { |
| if (!loose_enum_test<Enum>(e_val)) { |
| base::internal::WarnEnumCastError(e_val); |
| } |
| return static_cast<Enum>(e_val); |
| } |
| |
| template <typename Enum> |
| inline Enum tight_enum_cast(int e_val) { |
| if (!tight_enum_test<Enum>(e_val)) { |
| base::internal::WarnEnumCastError(e_val); |
| } |
| return static_cast<Enum>(e_val); |
| } |
| |
| #endif // BASE_CASTS_H_ |