From 8f612ebb152fb7e05643a2bcf78cb89a8c0641ad Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 3 Jul 2018 09:06:48 -0700 Subject: Export of internal Abseil changes. -- 71756e7176d15d52a4ee66cc25c088aedbca78f4 by Abseil Team : internal change PiperOrigin-RevId: 203131836 -- 2e80b965b590fd6459f45413215690980eb50960 by Matt Calabrese : Tighten type requirements for use of absl::bit_cast. Ideally, the constraints should depend on std::is_trivally_copyable, but a combination of supported configurations and lack of intrinsic support for bit_cast makes this not currently feasible. In a future change we should introduce more proper preprocessor branching and workarounds to better emulate the trait. PiperOrigin-RevId: 202950382 GitOrigin-RevId: 71756e7176d15d52a4ee66cc25c088aedbca78f4 Change-Id: If58840d1e4d801817be85cbf99a475c31fa94fe0 --- absl/base/casts.h | 51 ++++++++++++++++++++++++++++++++++++++++++++++++- absl/meta/type_traits.h | 2 ++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/absl/base/casts.h b/absl/base/casts.h index 8bd5264d..20fd34da 100644 --- a/absl/base/casts.h +++ b/absl/base/casts.h @@ -25,12 +25,36 @@ #define ABSL_BASE_CASTS_H_ #include +#include #include #include "absl/base/internal/identity.h" +#include "absl/base/macros.h" namespace absl { +namespace internal_casts { + +// NOTE: Not a fully compliant implementation of `std::is_trivially_copyable`. +// TODO(calabrese) Branch on implementations that directly provide +// `std::is_trivially_copyable`, create a more rigorous workaround, and publicly +// expose in meta/type_traits. +template +struct is_trivially_copyable + : std::integral_constant< + bool, std::is_destructible::value&& __has_trivial_destructor(T) && + __has_trivial_copy(T) && __has_trivial_assign(T)> {}; + +template +struct is_bitcastable + : std::integral_constant::value && + is_trivially_copyable::value && + std::is_default_constructible::value> {}; + +} // namespace internal_casts + // implicit_cast() // // Performs an implicit conversion between types following the language @@ -125,7 +149,32 @@ inline To implicit_cast(typename absl::internal::identity_t to) { // and reading its bits back using a different type. A `bit_cast()` avoids this // issue by implementing its casts using `memcpy()`, which avoids introducing // this undefined behavior. -template +// +// NOTE: The requirements here are more strict than the bit_cast of standard +// proposal p0476 due to the need for workarounds and lack of intrinsics. +// Specifically, this implementation also requires `Dest` to be +// default-constructible. +template < + typename Dest, typename Source, + typename std::enable_if::value, + int>::type = 0> +inline Dest bit_cast(const Source& source) { + Dest dest; + memcpy(static_cast(std::addressof(dest)), + static_cast(std::addressof(source)), sizeof(dest)); + return dest; +} + +// NOTE: This overload is only picked if the requirements of bit_cast are not +// met. It is therefore UB, but is provided temporarily as previous versions of +// this function template were unchecked. Do not use this in new code. +template < + typename Dest, typename Source, + typename std::enable_if< + !internal_casts::is_bitcastable::value, int>::type = 0> +ABSL_DEPRECATED( + "absl::bit_cast type requirements were violated. Update the types being " + "used such that they are the same size and are both TriviallyCopyable.") inline Dest bit_cast(const Source& source) { static_assert(sizeof(Dest) == sizeof(Source), "Source and destination types should have equal sizes."); diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h index 88af17c3..c3e01fe2 100644 --- a/absl/meta/type_traits.h +++ b/absl/meta/type_traits.h @@ -369,4 +369,6 @@ struct IsHashEnabled } // namespace type_traits_internal } // namespace absl + + #endif // ABSL_META_TYPE_TRAITS_H_ -- cgit v1.2.3