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:
		
							parent
							
								
									134496a31d
								
							
						
					
					
						commit
						8f612ebb15
					
				
					 2 changed files with 52 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -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.");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -369,4 +369,6 @@ struct IsHashEnabled
 | 
			
		|||
}  // namespace type_traits_internal
 | 
			
		||||
 | 
			
		||||
}  // namespace absl
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif  // ABSL_META_TYPE_TRAITS_H_
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue