Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame] | 1 | // Copyright 2016 The Chromium Authors |
tapted | 174fde3 | 2016-01-14 06:26:37 | [diff] [blame] | 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_BIT_CAST_H_ |
| 6 | #define BASE_BIT_CAST_H_ |
| 7 | |
Avi Drissman | fdd01ea | 2022-04-28 19:41:17 | [diff] [blame] | 8 | #include <type_traits> |
| 9 | |
Peter Kasting | cc88ac05 | 2022-05-03 09:58:01 | [diff] [blame] | 10 | namespace base { |
| 11 | |
Avi Drissman | 70cb7f7 | 2023-12-12 17:44:37 | [diff] [blame] | 12 | // This is an equivalent to C++20's std::bit_cast<>(), but with additional |
| 13 | // warnings. It morally does what `*reinterpret_cast<Dest*>(&source)` does, but |
| 14 | // the cast/deref pair is undefined behavior, while bit_cast<>() isn't. |
| 15 | // |
| 16 | // This is not a magic "get out of UB free" card. This must only be used on |
| 17 | // values, not on references or pointers. For pointers, use |
| 18 | // reinterpret_cast<>(), and then look at https://eel.is/c++draft/basic.lval#11 |
| 19 | // as that's probably UB also. |
jfb | d81c1ce | 2016-04-05 20:50:35 | [diff] [blame] | 20 | |
Avi Drissman | 70cb7f7 | 2023-12-12 17:44:37 | [diff] [blame] | 21 | template <class Dest, class Source> |
| 22 | constexpr Dest bit_cast(const Source& source) { |
| 23 | static_assert(!std::is_pointer_v<Source>, |
| 24 | "bit_cast must not be used on pointer types"); |
| 25 | static_assert(!std::is_pointer_v<Dest>, |
| 26 | "bit_cast must not be used on pointer types"); |
| 27 | static_assert(!std::is_reference_v<Source>, |
| 28 | "bit_cast must not be used on reference types"); |
| 29 | static_assert(!std::is_reference_v<Dest>, |
| 30 | "bit_cast must not be used on reference types"); |
| 31 | static_assert( |
| 32 | sizeof(Dest) == sizeof(Source), |
| 33 | "bit_cast requires source and destination types to be the same size"); |
| 34 | static_assert(std::is_trivially_copyable_v<Source>, |
| 35 | "bit_cast requires the source type to be trivially copyable"); |
| 36 | static_assert( |
| 37 | std::is_trivially_copyable_v<Dest>, |
| 38 | "bit_cast requires the destination type to be trivially copyable"); |
| 39 | |
| 40 | return __builtin_bit_cast(Dest, source); |
tapted | 174fde3 | 2016-01-14 06:26:37 | [diff] [blame] | 41 | } |
| 42 | |
Peter Kasting | cc88ac05 | 2022-05-03 09:58:01 | [diff] [blame] | 43 | } // namespace base |
| 44 | |
tapted | 174fde3 | 2016-01-14 06:26:37 | [diff] [blame] | 45 | #endif // BASE_BIT_CAST_H_ |