Guest User

bit_cast

a guest
Oct 15th, 2013
363
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.80 KB | None | 0 0
  1. #include <cstring>     // memcpy
  2. #include <type_traits> // is_trivially_copyable
  3.  
  4. // http://src.chromium.org/viewvc/chrome/trunk/src/base/basictypes.h?view=markup
  5.  
  6. // bit_cast<Dest,Source> is a template function that implements the
  7. // equivalent of "*reinterpret_cast<Dest*>(&source)".  We need this in
  8. // very low-level functions like the protobuf library and fast math
  9. // support.
  10. //
  11. //   float f = 3.14159265358979;
  12. //   int i = bit_cast<int32>(f);
  13. //   // i = 0x40490fdb
  14. //
  15. // The classical address-casting method is:
  16. //
  17. //   // WRONG
  18. //   float f = 3.14159265358979;            // WRONG
  19. //   int i = * reinterpret_cast<int*>(&f);  // WRONG
  20. //
  21. // The address-casting method actually produces undefined behavior
  22. // according to ISO C++ specification section 3.10 -15 -.  Roughly, this
  23. // section says: if an object in memory has one type, and a program
  24. // accesses it with a different type, then the result is undefined
  25. // behavior for most values of "different type".
  26. //
  27. // This is true for any cast syntax, either *(int*)&f or
  28. // *reinterpret_cast<int*>(&f).  And it is particularly true for
  29. // conversions betweeen integral lvalues and floating-point lvalues.
  30. //
  31. // The purpose of 3.10 -15- is to allow optimizing compilers to assume
  32. // that expressions with different types refer to different memory.  gcc
  33. // 4.0.1 has an optimizer that takes advantage of this.  So a
  34. // non-conforming program quietly produces wildly incorrect output.
  35. //
  36. // The problem is not the use of reinterpret_cast.  The problem is type
  37. // punning: holding an object in memory of one type and reading its bits
  38. // back using a different type.
  39. //
  40. // The C++ standard is more subtle and complex than this, but that
  41. // is the basic idea.
  42. //
  43. // Anyways ...
  44. //
  45. // bit_cast<> calls memcpy() which is blessed by the standard,
  46. // especially by the example in section 3.9 .  Also, of course,
  47. // bit_cast<> wraps up the nasty logic in one place.
  48. //
  49. // Fortunately memcpy() is very fast.  In optimized mode, with a
  50. // constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline
  51. // code with the minimal amount of data movement.  On a 32-bit system,
  52. // memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8)
  53. // compiles to two loads and two stores.
  54. //
  55. // I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1.
  56.  
  57. template <class Dest, class Source>
  58. inline Dest bit_cast(Source const &source) {
  59.     static_assert(sizeof(Dest)==sizeof(Source), "size of destination and source objects must be equal");
  60.     static_assert(std::is_trivially_copyable<Dest>::value, "destination type must be trivially copyable.");
  61.     static_assert(std::is_trivially_copyable<Source>::value, "source type must be trivially copyable");
  62.    
  63.     Dest dest;
  64.     std::memcpy(&dest, &source, sizeof(dest));
  65.     return dest;
  66. }
Advertisement
Add Comment
Please, Sign In to add comment