bit_cast.h 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // Copyright 2016 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. #ifndef BASE_BIT_CAST_H_
  5. #define BASE_BIT_CAST_H_
  6. #include <string.h>
  7. #include <type_traits>
  8. #include "base/compiler_specific.h"
  9. #include "base/template_util.h"
  10. #include "build/build_config.h"
  11. // bit_cast<Dest,Source> is a template function that implements the equivalent
  12. // of "*reinterpret_cast<Dest*>(&source)". We need this in very low-level
  13. // functions like the protobuf library and fast math support.
  14. //
  15. // float f = 3.14159265358979;
  16. // int i = bit_cast<int32_t>(f);
  17. // // i = 0x40490fdb
  18. //
  19. // The classical address-casting method is:
  20. //
  21. // // WRONG
  22. // float f = 3.14159265358979; // WRONG
  23. // int i = * reinterpret_cast<int*>(&f); // WRONG
  24. //
  25. // The address-casting method actually produces undefined behavior according to
  26. // the ISO C++98 specification, section 3.10 ("basic.lval"), paragraph 15.
  27. // (This did not substantially change in C++11.) Roughly, this section says: if
  28. // an object in memory has one type, and a program accesses it with a different
  29. // type, then the result is undefined behavior for most values of "different
  30. // type".
  31. //
  32. // This is true for any cast syntax, either *(int*)&f or
  33. // *reinterpret_cast<int*>(&f). And it is particularly true for conversions
  34. // between integral lvalues and floating-point lvalues.
  35. //
  36. // The purpose of this paragraph is to allow optimizing compilers to assume that
  37. // expressions with different types refer to different memory. Compilers are
  38. // known to take advantage of this. So a non-conforming program quietly
  39. // produces wildly incorrect output.
  40. //
  41. // The problem is not the use of reinterpret_cast. The problem is type punning:
  42. // holding an object in memory of one type and reading its bits back using a
  43. // different type.
  44. //
  45. // The C++ standard is more subtle and complex than this, but that is the basic
  46. // idea.
  47. //
  48. // Anyways ...
  49. //
  50. // bit_cast<> calls memcpy() which is blessed by the standard, especially by the
  51. // example in section 3.9 . Also, of course, bit_cast<> wraps up the nasty
  52. // logic in one place.
  53. //
  54. // Fortunately memcpy() is very fast. In optimized mode, compilers replace
  55. // calls to memcpy() with inline object code when the size argument is a
  56. // compile-time constant. On a 32-bit system, memcpy(d,s,4) compiles to one
  57. // load and one store, and memcpy(d,s,8) compiles to two loads and two stores.
  58. template <class Dest, class Source>
  59. inline Dest bit_cast(const Source& source) {
  60. static_assert(sizeof(Dest) == sizeof(Source),
  61. "bit_cast requires source and destination to be the same size");
  62. static_assert(base::is_trivially_copyable<Dest>::value,
  63. "bit_cast requires the destination type to be copyable");
  64. static_assert(base::is_trivially_copyable<Source>::value,
  65. "bit_cast requires the source type to be copyable");
  66. Dest dest;
  67. memcpy(&dest, &source, sizeof(dest));
  68. return dest;
  69. }
  70. #endif // BASE_BIT_CAST_H_