@ -25,12 +25,36 @@
# define ABSL_BASE_CASTS_H_
# define ABSL_BASE_CASTS_H_
# include <cstring>
# include <cstring>
# include <memory>
# include <type_traits>
# include <type_traits>
# include "absl/base/internal/identity.h"
# include "absl/base/internal/identity.h"
# include "absl/base/macros.h"
namespace absl {
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()
// implicit_cast()
//
//
// Performs an implicit conversion between types following the language
// 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
// and reading its bits back using a different type. A `bit_cast()` avoids this
// issue by implementing its casts using `memcpy()`, which avoids introducing
// issue by implementing its casts using `memcpy()`, which avoids introducing
// this undefined behavior.
// 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 ) {
inline Dest bit_cast ( const Source & source ) {
static_assert ( sizeof ( Dest ) = = sizeof ( Source ) ,
static_assert ( sizeof ( Dest ) = = sizeof ( Source ) ,
" Source and destination types should have equal sizes. " ) ;
" Source and destination types should have equal sizes. " ) ;