summaryrefslogtreecommitdiff
path: root/absl
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2018-07-03 09:06:48 -0700
committerGravatar Titus Winters <titus@google.com>2018-07-03 14:30:54 -0400
commit8f612ebb152fb7e05643a2bcf78cb89a8c0641ad (patch)
treee95c4eac84896870df0d9908baf5b3c9cd0ef066 /absl
parent134496a31d8b324f762de3bee9a002658c984456 (diff)
Export of internal Abseil changes.
-- 71756e7176d15d52a4ee66cc25c088aedbca78f4 by Abseil Team <absl-team@google.com>: internal change PiperOrigin-RevId: 203131836 -- 2e80b965b590fd6459f45413215690980eb50960 by Matt Calabrese <calabrese@google.com>: 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
Diffstat (limited to 'absl')
-rw-r--r--absl/base/casts.h51
-rw-r--r--absl/meta/type_traits.h2
2 files changed, 52 insertions, 1 deletions
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 <cstring>
+#include <memory>
#include <type_traits>
#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 <class T>
+struct is_trivially_copyable
+ : std::integral_constant<
+ bool, std::is_destructible<T>::value&& __has_trivial_destructor(T) &&
+ __has_trivial_copy(T) && __has_trivial_assign(T)> {};
+
+template <class Dest, class Source>
+struct is_bitcastable
+ : std::integral_constant<bool,
+ sizeof(Dest) == sizeof(Source) &&
+ is_trivially_copyable<Source>::value &&
+ is_trivially_copyable<Dest>::value &&
+ std::is_default_constructible<Dest>::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> 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 <typename Dest, typename Source>
+//
+// 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<internal_casts::is_bitcastable<Dest, Source>::value,
+ int>::type = 0>
+inline Dest bit_cast(const Source& source) {
+ Dest dest;
+ memcpy(static_cast<void*>(std::addressof(dest)),
+ static_cast<const void*>(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<Dest, Source>::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_