MRPT  2.0.4
bit_cast.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 // Copyright 2016 The Chromium Authors. All rights reserved.
11 // Use of this source code is governed by a BSD-style license that can be
12 // found in the LICENSE file.
13 #pragma once
14 #include <cstring>
15 #include <type_traits>
16 //#include "base/compiler_specific.h" // mrpt
17 //#include "base/template_util.h" // mrpt
18 //#include "build/build_config.h" // mrpt
19 // bit_cast<Dest,Source> is a template function that implements the equivalent
20 // of "*reinterpret_cast<Dest*>(&source)". We need this in very low-level
21 // functions like the protobuf library and fast math support.
22 //
23 // float f = 3.14159265358979;
24 // int i = bit_cast<int32_t>(f);
25 // // i = 0x40490fdb
26 //
27 // The classical address-casting method is:
28 //
29 // // WRONG
30 // float f = 3.14159265358979; // WRONG
31 // int i = * reinterpret_cast<int*>(&f); // WRONG
32 //
33 // The address-casting method actually produces undefined behavior according to
34 // the ISO C++98 specification, section 3.10 ("basic.lval"), paragraph 15.
35 // (This did not substantially change in C++11.) Roughly, this section says: if
36 // an object in memory has one type, and a program accesses it with a different
37 // type, then the result is undefined behavior for most values of "different
38 // type".
39 //
40 // This is true for any cast syntax, either *(int*)&f or
41 // *reinterpret_cast<int*>(&f). And it is particularly true for conversions
42 // between integral lvalues and floating-point lvalues.
43 //
44 // The purpose of this paragraph is to allow optimizing compilers to assume that
45 // expressions with different types refer to different memory. Compilers are
46 // known to take advantage of this. So a non-conforming program quietly
47 // produces wildly incorrect output.
48 //
49 // The problem is not the use of reinterpret_cast. The problem is type punning:
50 // holding an object in memory of one type and reading its bits back using a
51 // different type.
52 //
53 // The C++ standard is more subtle and complex than this, but that is the basic
54 // idea.
55 //
56 // Anyways ...
57 //
58 // bit_cast<> calls memcpy() which is blessed by the standard, especially by the
59 // example in section 3.9 . Also, of course, bit_cast<> wraps up the nasty
60 // logic in one place.
61 //
62 // Fortunately memcpy() is very fast. In optimized mode, compilers replace
63 // calls to memcpy() with inline object code when the size argument is a
64 // compile-time constant. On a 32-bit system, memcpy(d,s,4) compiles to one
65 // load and one store, and memcpy(d,s,8) compiles to two loads and two stores.
66 template <class Dest, class Source>
67 inline Dest bit_cast(const Source& source)
68 {
69  static_assert(
70  sizeof(Dest) == sizeof(Source),
71  "bit_cast requires source and destination to be the same size");
72  static_assert(
73  std::is_trivially_copyable<Dest>::value,
74  "bit_cast requires the destination type to be copyable");
75  static_assert(
76  std::is_trivially_copyable<Source>::value,
77  "bit_cast requires the source type to be copyable");
78  Dest dest;
79  memcpy(&dest, &source, sizeof(dest));
80  return dest;
81 }
Dest bit_cast(const Source &source)
Definition: bit_cast.h:67
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".



Page generated by Doxygen 1.8.14 for MRPT 2.0.4 Git: 33de1d0ad Sat Jun 20 11:02:42 2020 +0200 at sáb jun 20 17:35:17 CEST 2020