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
This commit is contained in:
Abseil Team 2018-07-03 09:06:48 -07:00 committed by Titus Winters
parent 134496a31d
commit 8f612ebb15
2 changed files with 52 additions and 1 deletions

View file

@ -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.");

View file

@ -369,4 +369,6 @@ struct IsHashEnabled
} // namespace type_traits_internal
} // namespace absl
#endif // ABSL_META_TYPE_TRAITS_H_