Commit 7b461233 by Derek Mauro Committed by Copybara-Service

Remove backfills of some type traits that are now fully supported

PiperOrigin-RevId: 512622121
Change-Id: If90aaf7939062bd475253c372d9d7950c98c7150
parent f2b52372
......@@ -237,15 +237,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
// ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
//
// Checks whether `std::is_trivially_destructible<T>` is supported.
//
// Notes: All supported compilers using libc++ support this feature, as does
// gcc >= 4.8.1 using libstdc++, and Visual Studio.
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
#error ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE cannot be directly set
#elif defined(_LIBCPP_VERSION) || defined(_MSC_VER) || \
(defined(__clang__) && __clang_major__ >= 15) || \
(!defined(__clang__) && defined(__GLIBCXX__) && \
ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(4, 8))
#define ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE 1
#endif
......@@ -253,36 +246,26 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
//
// Checks whether `std::is_trivially_default_constructible<T>` and
// `std::is_trivially_copy_constructible<T>` are supported.
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
#error ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set
#else
#define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1
#endif
// ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
//
// Checks whether `std::is_trivially_copy_assignable<T>` is supported.
// Notes: Clang with libc++ supports these features, as does gcc >= 7.4 with
// libstdc++, or gcc >= 8.2 with libc++, and Visual Studio (but not NVCC).
#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE)
#error ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set
#elif defined(ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE)
#error ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot directly set
#elif (defined(__clang__) && defined(_LIBCPP_VERSION)) || \
(defined(__clang__) && __clang_major__ >= 15) || \
(!defined(__clang__) && \
((ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(7, 4) && defined(__GLIBCXX__)) || \
(ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(8, 2) && \
defined(_LIBCPP_VERSION)))) || \
(defined(_MSC_VER) && !defined(__NVCC__) && !defined(__clang__))
#define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
#error ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot be directly set
#else
#define ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1
#endif
// ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE
//
// Checks whether `std::is_trivially_copyable<T>` is supported.
//
// Notes: Clang 15+ with libc++ supports these features, GCC hasn't been tested.
#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE)
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE
#error ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE cannot be directly set
#elif defined(__clang__) && (__clang_major__ >= 15)
#define ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE 1
#endif
......
......@@ -41,12 +41,6 @@
#include "absl/base/config.h"
// MSVC constructibility traits do not detect destructor properties and so our
// implementations should not use them as a source-of-truth.
#if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
#define ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION 1
#endif
// Defines the default alignment. `__STDCPP_DEFAULT_NEW_ALIGNMENT__` is a C++17
// feature.
#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
......@@ -58,57 +52,8 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
// Defined and documented later on in this file.
template <typename T>
struct is_trivially_destructible;
// Defined and documented later on in this file.
template <typename T>
struct is_trivially_move_assignable;
namespace type_traits_internal {
// Silence MSVC warnings about the destructor being defined as deleted.
#if defined(_MSC_VER) && !defined(__GNUC__)
#pragma warning(push)
#pragma warning(disable : 4624)
#endif // defined(_MSC_VER) && !defined(__GNUC__)
template <class T>
union SingleMemberUnion {
T t;
};
// Restore the state of the destructor warning that was silenced above.
#if defined(_MSC_VER) && !defined(__GNUC__)
#pragma warning(pop)
#endif // defined(_MSC_VER) && !defined(__GNUC__)
template <class T>
struct IsTriviallyMoveConstructibleObject
: std::integral_constant<
bool, std::is_move_constructible<
type_traits_internal::SingleMemberUnion<T>>::value &&
absl::is_trivially_destructible<T>::value> {};
template <class T>
struct IsTriviallyCopyConstructibleObject
: std::integral_constant<
bool, std::is_copy_constructible<
type_traits_internal::SingleMemberUnion<T>>::value &&
absl::is_trivially_destructible<T>::value> {};
template <class T>
struct IsTriviallyMoveAssignableReference : std::false_type {};
template <class T>
struct IsTriviallyMoveAssignableReference<T&>
: absl::is_trivially_move_assignable<T>::type {};
template <class T>
struct IsTriviallyMoveAssignableReference<T&&>
: absl::is_trivially_move_assignable<T>::type {};
template <typename... Ts>
struct VoidTImpl {
using type = void;
......@@ -157,39 +102,8 @@ template <class To, template <class...> class Op, class... Args>
struct is_detected_convertible
: is_detected_convertible_impl<void, To, Op, Args...>::type {};
template <typename T>
using IsCopyAssignableImpl =
decltype(std::declval<T&>() = std::declval<const T&>());
template <typename T>
using IsMoveAssignableImpl = decltype(std::declval<T&>() = std::declval<T&&>());
} // namespace type_traits_internal
// MSVC 19.20 has a regression that causes our workarounds to fail, but their
// std forms now appear to be compliant.
#if defined(_MSC_VER) && !defined(__clang__) && (_MSC_VER >= 1920)
template <typename T>
using is_copy_assignable = std::is_copy_assignable<T>;
template <typename T>
using is_move_assignable = std::is_move_assignable<T>;
#else
template <typename T>
struct is_copy_assignable : type_traits_internal::is_detected<
type_traits_internal::IsCopyAssignableImpl, T> {
};
template <typename T>
struct is_move_assignable : type_traits_internal::is_detected<
type_traits_internal::IsMoveAssignableImpl, T> {
};
#endif
// void_t()
//
// Ignores the type of any its arguments and returns `void`. In general, this
......@@ -270,246 +184,29 @@ struct is_function
bool, !(std::is_reference<T>::value ||
std::is_const<typename std::add_const<T>::type>::value)> {};
// is_copy_assignable()
// is_move_assignable()
// is_trivially_destructible()
//
// Determines whether the passed type `T` is trivially destructible.
//
// This metafunction is designed to be a drop-in replacement for the C++11
// `std::is_trivially_destructible()` metafunction for platforms that have
// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
// fully support C++11, we check whether this yields the same result as the std
// implementation.
//
// NOTE: the extensions (__has_trivial_xxx) are implemented in gcc (version >=
// 4.3) and clang. Since we are supporting libstdc++ > 4.7, they should always
// be present. These extensions are documented at
// https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html#Type-Traits.
template <typename T>
struct is_trivially_destructible
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
: std::is_trivially_destructible<T> {
#else
: std::integral_constant<bool, __has_trivial_destructor(T) &&
std::is_destructible<T>::value> {
#endif
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
private:
static constexpr bool compliant = std::is_trivially_destructible<T>::value ==
is_trivially_destructible::value;
static_assert(compliant || std::is_trivially_destructible<T>::value,
"Not compliant with std::is_trivially_destructible; "
"Standard: false, Implementation: true");
static_assert(compliant || !std::is_trivially_destructible<T>::value,
"Not compliant with std::is_trivially_destructible; "
"Standard: true, Implementation: false");
#endif // ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
};
// is_trivially_default_constructible()
//
// Determines whether the passed type `T` is trivially default constructible.
//
// This metafunction is designed to be a drop-in replacement for the C++11
// `std::is_trivially_default_constructible()` metafunction for platforms that
// have incomplete C++11 support (such as libstdc++ 4.x). On any platforms that
// do fully support C++11, we check whether this yields the same result as the
// std implementation.
//
// NOTE: according to the C++ standard, Section: 20.15.4.3 [meta.unary.prop]
// "The predicate condition for a template specialization is_constructible<T,
// Args...> shall be satisfied if and only if the following variable
// definition would be well-formed for some invented variable t:
//
// T t(declval<Args>()...);
//
// is_trivially_constructible<T, Args...> additionally requires that the
// variable definition does not call any operation that is not trivial.
// For the purposes of this check, the call to std::declval is considered
// trivial."
//
// Notes from https://en.cppreference.com/w/cpp/types/is_constructible:
// In many implementations, is_nothrow_constructible also checks if the
// destructor throws because it is effectively noexcept(T(arg)). Same
// applies to is_trivially_constructible, which, in these implementations, also
// requires that the destructor is trivial.
// GCC bug 51452: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452
// LWG issue 2116: http://cplusplus.github.io/LWG/lwg-active.html#2116.
//
// "T obj();" need to be well-formed and not call any nontrivial operation.
// Nontrivially destructible types will cause the expression to be nontrivial.
template <typename T>
struct is_trivially_default_constructible
#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE)
: std::is_trivially_default_constructible<T> {
#else
: std::integral_constant<bool, __has_trivial_constructor(T) &&
std::is_default_constructible<T>::value &&
is_trivially_destructible<T>::value> {
#endif
#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
!defined( \
ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
private:
static constexpr bool compliant =
std::is_trivially_default_constructible<T>::value ==
is_trivially_default_constructible::value;
static_assert(compliant || std::is_trivially_default_constructible<T>::value,
"Not compliant with std::is_trivially_default_constructible; "
"Standard: false, Implementation: true");
static_assert(compliant || !std::is_trivially_default_constructible<T>::value,
"Not compliant with std::is_trivially_default_constructible; "
"Standard: true, Implementation: false");
#endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
};
// is_trivially_move_constructible()
//
// Determines whether the passed type `T` is trivially move constructible.
//
// This metafunction is designed to be a drop-in replacement for the C++11
// `std::is_trivially_move_constructible()` metafunction for platforms that have
// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
// fully support C++11, we check whether this yields the same result as the std
// implementation.
//
// NOTE: `T obj(declval<T>());` needs to be well-formed and not call any
// nontrivial operation. Nontrivially destructible types will cause the
// expression to be nontrivial.
template <typename T>
struct is_trivially_move_constructible
#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE)
: std::is_trivially_move_constructible<T> {
#else
: std::conditional<
std::is_object<T>::value && !std::is_array<T>::value,
type_traits_internal::IsTriviallyMoveConstructibleObject<T>,
std::is_reference<T>>::type::type {
#endif
#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
!defined( \
ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
private:
static constexpr bool compliant =
std::is_trivially_move_constructible<T>::value ==
is_trivially_move_constructible::value;
static_assert(compliant || std::is_trivially_move_constructible<T>::value,
"Not compliant with std::is_trivially_move_constructible; "
"Standard: false, Implementation: true");
static_assert(compliant || !std::is_trivially_move_constructible<T>::value,
"Not compliant with std::is_trivially_move_constructible; "
"Standard: true, Implementation: false");
#endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
};
// is_trivially_copy_constructible()
//
// Determines whether the passed type `T` is trivially copy constructible.
//
// This metafunction is designed to be a drop-in replacement for the C++11
// `std::is_trivially_copy_constructible()` metafunction for platforms that have
// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
// fully support C++11, we check whether this yields the same result as the std
// implementation.
//
// NOTE: `T obj(declval<const T&>());` needs to be well-formed and not call any
// nontrivial operation. Nontrivially destructible types will cause the
// expression to be nontrivial.
template <typename T>
struct is_trivially_copy_constructible
: std::conditional<
std::is_object<T>::value && !std::is_array<T>::value,
type_traits_internal::IsTriviallyCopyConstructibleObject<T>,
std::is_lvalue_reference<T>>::type::type {
#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
!defined( \
ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
private:
static constexpr bool compliant =
std::is_trivially_copy_constructible<T>::value ==
is_trivially_copy_constructible::value;
static_assert(compliant || std::is_trivially_copy_constructible<T>::value,
"Not compliant with std::is_trivially_copy_constructible; "
"Standard: false, Implementation: true");
static_assert(compliant || !std::is_trivially_copy_constructible<T>::value,
"Not compliant with std::is_trivially_copy_constructible; "
"Standard: true, Implementation: false");
#endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
};
// is_trivially_move_assignable()
//
// Determines whether the passed type `T` is trivially move assignable.
//
// This metafunction is designed to be a drop-in replacement for the C++11
// `std::is_trivially_move_assignable()` metafunction for platforms that have
// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
// fully support C++11, we check whether this yields the same result as the std
// implementation.
//
// NOTE: `is_assignable<T, U>::value` is `true` if the expression
// `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated
// operand. `is_trivially_assignable<T, U>` requires the assignment to call no
// operation that is not trivial. `is_trivially_copy_assignable<T>` is simply
// `is_trivially_assignable<T&, T>`.
template <typename T>
struct is_trivially_move_assignable
: std::conditional<
std::is_object<T>::value && !std::is_array<T>::value &&
std::is_move_assignable<T>::value,
std::is_move_assignable<type_traits_internal::SingleMemberUnion<T>>,
type_traits_internal::IsTriviallyMoveAssignableReference<T>>::type::
type {
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
private:
static constexpr bool compliant =
std::is_trivially_move_assignable<T>::value ==
is_trivially_move_assignable::value;
static_assert(compliant || std::is_trivially_move_assignable<T>::value,
"Not compliant with std::is_trivially_move_assignable; "
"Standard: false, Implementation: true");
static_assert(compliant || !std::is_trivially_move_assignable<T>::value,
"Not compliant with std::is_trivially_move_assignable; "
"Standard: true, Implementation: false");
#endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
};
// is_trivially_copy_assignable()
//
// Determines whether the passed type `T` is trivially copy assignable.
//
// This metafunction is designed to be a drop-in replacement for the C++11
// `std::is_trivially_copy_assignable()` metafunction for platforms that have
// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
// fully support C++11, we check whether this yields the same result as the std
// implementation.
//
// NOTE: `is_assignable<T, U>::value` is `true` if the expression
// `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated
// operand. `is_trivially_assignable<T, U>` requires the assignment to call no
// operation that is not trivial. `is_trivially_copy_assignable<T>` is simply
// `is_trivially_assignable<T&, const T&>`.
template <typename T>
struct is_trivially_copy_assignable
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
: std::is_trivially_copy_assignable<T> {
#else
: std::integral_constant<
bool, __has_trivial_assign(typename std::remove_reference<T>::type) &&
absl::is_copy_assignable<T>::value> {
#endif
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
private:
static constexpr bool compliant =
std::is_trivially_copy_assignable<T>::value ==
is_trivially_copy_assignable::value;
static_assert(compliant || std::is_trivially_copy_assignable<T>::value,
"Not compliant with std::is_trivially_copy_assignable; "
"Standard: false, Implementation: true");
static_assert(compliant || !std::is_trivially_copy_assignable<T>::value,
"Not compliant with std::is_trivially_copy_assignable; "
"Standard: true, Implementation: false");
#endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
};
// Historical note: Abseil once provided implementations of these type traits
// for platforms that lacked full support. New code should prefer to use the
// std variants.
//
// See the documentation for the STL <type_traits> header for more information:
// https://en.cppreference.com/w/cpp/header/type_traits
using std::is_copy_assignable;
using std::is_move_assignable;
using std::is_trivially_copy_assignable;
using std::is_trivially_copy_constructible;
using std::is_trivially_default_constructible;
using std::is_trivially_destructible;
using std::is_trivially_move_assignable;
using std::is_trivially_move_constructible;
#if defined(__cpp_lib_remove_cvref) && __cpp_lib_remove_cvref >= 201711L
template <typename T>
......@@ -533,52 +230,11 @@ using remove_cvref_t = typename remove_cvref<T>::type;
#endif
namespace type_traits_internal {
// is_trivially_copyable()
//
// Determines whether the passed type `T` is trivially copyable.
//
// This metafunction is designed to be a drop-in replacement for the C++11
// `std::is_trivially_copyable()` metafunction for platforms that have
// incomplete C++11 support (such as libstdc++ 4.x). We use the C++17 definition
// of TriviallyCopyable.
//
// NOTE: `is_trivially_copyable<T>::value` is `true` if all of T's copy/move
// constructors/assignment operators are trivial or deleted, T has at least
// one non-deleted copy/move constructor/assignment operator, and T is trivially
// destructible. Arrays of trivially copyable types are trivially copyable.
//
// We expose this metafunction only for internal use within absl.
#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE)
template <typename T>
struct is_trivially_copyable : std::is_trivially_copyable<T> {};
#else
template <typename T>
class is_trivially_copyable_impl {
using ExtentsRemoved = typename std::remove_all_extents<T>::type;
static constexpr bool kIsCopyOrMoveConstructible =
std::is_copy_constructible<ExtentsRemoved>::value ||
std::is_move_constructible<ExtentsRemoved>::value;
static constexpr bool kIsCopyOrMoveAssignable =
absl::is_copy_assignable<ExtentsRemoved>::value ||
absl::is_move_assignable<ExtentsRemoved>::value;
public:
static constexpr bool kValue =
(__has_trivial_copy(ExtentsRemoved) || !kIsCopyOrMoveConstructible) &&
(__has_trivial_assign(ExtentsRemoved) || !kIsCopyOrMoveAssignable) &&
(kIsCopyOrMoveConstructible || kIsCopyOrMoveAssignable) &&
is_trivially_destructible<ExtentsRemoved>::value &&
// We need to check for this explicitly because otherwise we'll say
// references are trivial copyable when compiled by MSVC.
!std::is_reference<ExtentsRemoved>::value;
};
template <typename T>
struct is_trivially_copyable
: std::integral_constant<
bool, type_traits_internal::is_trivially_copyable_impl<T>::kValue> {};
#endif
// An implementation of std::is_trivially_copyable was once provided for
// internal use within absl.
// TODO(absl-team): Replace absl::type_traits_internal::is_trivially_copyable
// with std::is_trivially_copyable and delete this using declaration.
using std::is_trivially_copyable;
} // namespace type_traits_internal
// -----------------------------------------------------------------------------
......
......@@ -352,29 +352,6 @@ class Base {
virtual ~Base() {}
};
// Old versions of libc++, around Clang 3.5 to 3.6, consider deleted destructors
// as also being trivial. With the resolution of CWG 1928 and CWG 1734, this
// is no longer considered true and has thus been amended.
// Compiler Explorer: https://godbolt.org/g/zT59ZL
// CWG issue 1734: http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1734
// CWG issue 1928: http://open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#1928
#if !defined(_LIBCPP_VERSION) || _LIBCPP_VERSION >= 3700
#define ABSL_TRIVIALLY_DESTRUCTIBLE_CONSIDER_DELETED_DESTRUCTOR_NOT_TRIVIAL 1
#endif
// As of the moment, GCC versions >5.1 have a problem compiling for
// std::is_trivially_default_constructible<NontrivialDestructor[10]>, where
// NontrivialDestructor is a struct with a custom nontrivial destructor. Note
// that this problem only occurs for arrays of a known size, so something like
// std::is_trivially_default_constructible<NontrivialDestructor[]> does not
// have any problems.
// Compiler Explorer: https://godbolt.org/g/dXRbdK
// GCC bug 83689: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83689
#if defined(__clang__) || defined(_MSC_VER) || \
(defined(__GNUC__) && __GNUC__ < 5)
#define ABSL_GCC_BUG_TRIVIALLY_CONSTRUCTIBLE_ON_ARRAY_OF_NONTRIVIAL 1
#endif
TEST(TypeTraitsTest, TestIsFunction) {
struct Callable {
void operator()() {}
......@@ -391,562 +368,6 @@ TEST(TypeTraitsTest, TestIsFunction) {
EXPECT_FALSE(absl::is_function<Callable>::value);
}
TEST(TypeTraitsTest, TestTrivialDestructor) {
// Verify that arithmetic types and pointers have trivial destructors.
EXPECT_TRUE(absl::is_trivially_destructible<bool>::value);
EXPECT_TRUE(absl::is_trivially_destructible<char>::value);
EXPECT_TRUE(absl::is_trivially_destructible<unsigned char>::value);
EXPECT_TRUE(absl::is_trivially_destructible<signed char>::value);
EXPECT_TRUE(absl::is_trivially_destructible<wchar_t>::value);
EXPECT_TRUE(absl::is_trivially_destructible<int>::value);
EXPECT_TRUE(absl::is_trivially_destructible<unsigned int>::value);
EXPECT_TRUE(absl::is_trivially_destructible<int16_t>::value);
EXPECT_TRUE(absl::is_trivially_destructible<uint16_t>::value);
EXPECT_TRUE(absl::is_trivially_destructible<int64_t>::value);
EXPECT_TRUE(absl::is_trivially_destructible<uint64_t>::value);
EXPECT_TRUE(absl::is_trivially_destructible<float>::value);
EXPECT_TRUE(absl::is_trivially_destructible<double>::value);
EXPECT_TRUE(absl::is_trivially_destructible<long double>::value);
EXPECT_TRUE(absl::is_trivially_destructible<std::string*>::value);
EXPECT_TRUE(absl::is_trivially_destructible<Trivial*>::value);
EXPECT_TRUE(absl::is_trivially_destructible<const std::string*>::value);
EXPECT_TRUE(absl::is_trivially_destructible<const Trivial*>::value);
EXPECT_TRUE(absl::is_trivially_destructible<std::string**>::value);
EXPECT_TRUE(absl::is_trivially_destructible<Trivial**>::value);
// classes with destructors
EXPECT_TRUE(absl::is_trivially_destructible<Trivial>::value);
EXPECT_TRUE(absl::is_trivially_destructible<TrivialDestructor>::value);
// Verify that types with a nontrivial or deleted destructor
// are marked as such.
EXPECT_FALSE(absl::is_trivially_destructible<NontrivialDestructor>::value);
#ifdef ABSL_TRIVIALLY_DESTRUCTIBLE_CONSIDER_DELETED_DESTRUCTOR_NOT_TRIVIAL
EXPECT_FALSE(absl::is_trivially_destructible<DeletedDestructor>::value);
#endif
// simple_pair of such types is trivial
EXPECT_TRUE((absl::is_trivially_destructible<simple_pair<int, int>>::value));
EXPECT_TRUE((absl::is_trivially_destructible<
simple_pair<Trivial, TrivialDestructor>>::value));
// Verify that types without trivial destructors are correctly marked as such.
EXPECT_FALSE(absl::is_trivially_destructible<std::string>::value);
EXPECT_FALSE(absl::is_trivially_destructible<std::vector<int>>::value);
// Verify that simple_pairs of types without trivial destructors
// are not marked as trivial.
EXPECT_FALSE((absl::is_trivially_destructible<
simple_pair<int, std::string>>::value));
EXPECT_FALSE((absl::is_trivially_destructible<
simple_pair<std::string, int>>::value));
// array of such types is trivial
using int10 = int[10];
EXPECT_TRUE(absl::is_trivially_destructible<int10>::value);
using Trivial10 = Trivial[10];
EXPECT_TRUE(absl::is_trivially_destructible<Trivial10>::value);
using TrivialDestructor10 = TrivialDestructor[10];
EXPECT_TRUE(absl::is_trivially_destructible<TrivialDestructor10>::value);
// Conversely, the opposite also holds.
using NontrivialDestructor10 = NontrivialDestructor[10];
EXPECT_FALSE(absl::is_trivially_destructible<NontrivialDestructor10>::value);
}
TEST(TypeTraitsTest, TestTrivialDefaultCtor) {
// arithmetic types and pointers have trivial default constructors.
EXPECT_TRUE(absl::is_trivially_default_constructible<bool>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<char>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<unsigned char>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<signed char>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<wchar_t>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<int>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<unsigned int>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<int16_t>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<uint16_t>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<int64_t>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<uint64_t>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<float>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<double>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<long double>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<std::string*>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<Trivial*>::value);
EXPECT_TRUE(
absl::is_trivially_default_constructible<const std::string*>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<const Trivial*>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<std::string**>::value);
EXPECT_TRUE(absl::is_trivially_default_constructible<Trivial**>::value);
// types with compiler generated default ctors
EXPECT_TRUE(absl::is_trivially_default_constructible<Trivial>::value);
EXPECT_TRUE(
absl::is_trivially_default_constructible<TrivialDefaultCtor>::value);
// Verify that types without them are not.
EXPECT_FALSE(
absl::is_trivially_default_constructible<NontrivialDefaultCtor>::value);
EXPECT_FALSE(
absl::is_trivially_default_constructible<DeletedDefaultCtor>::value);
// types with nontrivial destructor are nontrivial
EXPECT_FALSE(
absl::is_trivially_default_constructible<NontrivialDestructor>::value);
// types with vtables
EXPECT_FALSE(absl::is_trivially_default_constructible<Base>::value);
// Verify that simple_pair has trivial constructors where applicable.
EXPECT_TRUE((absl::is_trivially_default_constructible<
simple_pair<int, char*>>::value));
EXPECT_TRUE((absl::is_trivially_default_constructible<
simple_pair<int, Trivial>>::value));
EXPECT_TRUE((absl::is_trivially_default_constructible<
simple_pair<int, TrivialDefaultCtor>>::value));
// Verify that types without trivial constructors are
// correctly marked as such.
EXPECT_FALSE(absl::is_trivially_default_constructible<std::string>::value);
EXPECT_FALSE(
absl::is_trivially_default_constructible<std::vector<int>>::value);
// Verify that simple_pairs of types without trivial constructors
// are not marked as trivial.
EXPECT_FALSE((absl::is_trivially_default_constructible<
simple_pair<int, std::string>>::value));
EXPECT_FALSE((absl::is_trivially_default_constructible<
simple_pair<std::string, int>>::value));
// Verify that arrays of such types are trivially default constructible
using int10 = int[10];
EXPECT_TRUE(absl::is_trivially_default_constructible<int10>::value);
using Trivial10 = Trivial[10];
EXPECT_TRUE(absl::is_trivially_default_constructible<Trivial10>::value);
using TrivialDefaultCtor10 = TrivialDefaultCtor[10];
EXPECT_TRUE(
absl::is_trivially_default_constructible<TrivialDefaultCtor10>::value);
// Conversely, the opposite also holds.
#ifdef ABSL_GCC_BUG_TRIVIALLY_CONSTRUCTIBLE_ON_ARRAY_OF_NONTRIVIAL
using NontrivialDefaultCtor10 = NontrivialDefaultCtor[10];
EXPECT_FALSE(
absl::is_trivially_default_constructible<NontrivialDefaultCtor10>::value);
#endif
}
// GCC prior to 7.4 had a bug in its trivially-constructible traits
// (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80654).
// This test makes sure that we do not depend on the trait in these cases when
// implementing absl triviality traits.
template <class T>
struct BadConstructors {
BadConstructors() { static_assert(T::value, ""); }
BadConstructors(BadConstructors&&) { static_assert(T::value, ""); }
BadConstructors(const BadConstructors&) { static_assert(T::value, ""); }
};
TEST(TypeTraitsTest, TestTrivialityBadConstructors) {
using BadType = BadConstructors<int>;
EXPECT_FALSE(absl::is_trivially_default_constructible<BadType>::value);
EXPECT_FALSE(absl::is_trivially_move_constructible<BadType>::value);
EXPECT_FALSE(absl::is_trivially_copy_constructible<BadType>::value);
}
TEST(TypeTraitsTest, TestTrivialMoveCtor) {
// Verify that arithmetic types and pointers have trivial move
// constructors.
EXPECT_TRUE(absl::is_trivially_move_constructible<bool>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<char>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<unsigned char>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<signed char>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<wchar_t>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<int>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<unsigned int>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<int16_t>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<uint16_t>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<int64_t>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<uint64_t>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<float>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<double>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<long double>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<std::string*>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<Trivial*>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<const std::string*>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<const Trivial*>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<std::string**>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<Trivial**>::value);
// Reference types
EXPECT_TRUE(absl::is_trivially_move_constructible<int&>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<int&&>::value);
// types with compiler generated move ctors
EXPECT_TRUE(absl::is_trivially_move_constructible<Trivial>::value);
EXPECT_TRUE(absl::is_trivially_move_constructible<TrivialMoveCtor>::value);
// Verify that types without them (i.e. nontrivial or deleted) are not.
EXPECT_FALSE(
absl::is_trivially_move_constructible<NontrivialCopyCtor>::value);
EXPECT_FALSE(absl::is_trivially_move_constructible<DeletedCopyCtor>::value);
EXPECT_FALSE(
absl::is_trivially_move_constructible<NonCopyableOrMovable>::value);
// type with nontrivial destructor are nontrivial move construbtible
EXPECT_FALSE(
absl::is_trivially_move_constructible<NontrivialDestructor>::value);
// types with vtables
EXPECT_FALSE(absl::is_trivially_move_constructible<Base>::value);
// Verify that simple_pair of such types is trivially move constructible
EXPECT_TRUE(
(absl::is_trivially_move_constructible<simple_pair<int, char*>>::value));
EXPECT_TRUE((
absl::is_trivially_move_constructible<simple_pair<int, Trivial>>::value));
EXPECT_TRUE((absl::is_trivially_move_constructible<
simple_pair<int, TrivialMoveCtor>>::value));
// Verify that types without trivial move constructors are
// correctly marked as such.
EXPECT_FALSE(absl::is_trivially_move_constructible<std::string>::value);
EXPECT_FALSE(absl::is_trivially_move_constructible<std::vector<int>>::value);
// Verify that simple_pairs of types without trivial move constructors
// are not marked as trivial.
EXPECT_FALSE((absl::is_trivially_move_constructible<
simple_pair<int, std::string>>::value));
EXPECT_FALSE((absl::is_trivially_move_constructible<
simple_pair<std::string, int>>::value));
// Verify that arrays are not
using int10 = int[10];
EXPECT_FALSE(absl::is_trivially_move_constructible<int10>::value);
}
TEST(TypeTraitsTest, TestTrivialCopyCtor) {
// Verify that arithmetic types and pointers have trivial copy
// constructors.
EXPECT_TRUE(absl::is_trivially_copy_constructible<bool>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<char>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<unsigned char>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<signed char>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<wchar_t>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<int>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<unsigned int>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<int16_t>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<uint16_t>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<int64_t>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<uint64_t>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<float>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<double>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<long double>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<std::string*>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<Trivial*>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<const std::string*>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<const Trivial*>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<std::string**>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<Trivial**>::value);
// Reference types
EXPECT_TRUE(absl::is_trivially_copy_constructible<int&>::value);
EXPECT_FALSE(absl::is_trivially_copy_constructible<int&&>::value);
// types with compiler generated copy ctors
EXPECT_TRUE(absl::is_trivially_copy_constructible<Trivial>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<TrivialCopyCtor>::value);
// Verify that types without them (i.e. nontrivial or deleted) are not.
EXPECT_FALSE(
absl::is_trivially_copy_constructible<NontrivialCopyCtor>::value);
EXPECT_FALSE(absl::is_trivially_copy_constructible<DeletedCopyCtor>::value);
EXPECT_FALSE(
absl::is_trivially_copy_constructible<MovableNonCopyable>::value);
EXPECT_FALSE(
absl::is_trivially_copy_constructible<NonCopyableOrMovable>::value);
// type with nontrivial destructor are nontrivial copy construbtible
EXPECT_FALSE(
absl::is_trivially_copy_constructible<NontrivialDestructor>::value);
// types with vtables
EXPECT_FALSE(absl::is_trivially_copy_constructible<Base>::value);
// Verify that simple_pair of such types is trivially copy constructible
EXPECT_TRUE(
(absl::is_trivially_copy_constructible<simple_pair<int, char*>>::value));
EXPECT_TRUE((
absl::is_trivially_copy_constructible<simple_pair<int, Trivial>>::value));
EXPECT_TRUE((absl::is_trivially_copy_constructible<
simple_pair<int, TrivialCopyCtor>>::value));
// Verify that types without trivial copy constructors are
// correctly marked as such.
EXPECT_FALSE(absl::is_trivially_copy_constructible<std::string>::value);
EXPECT_FALSE(absl::is_trivially_copy_constructible<std::vector<int>>::value);
// Verify that simple_pairs of types without trivial copy constructors
// are not marked as trivial.
EXPECT_FALSE((absl::is_trivially_copy_constructible<
simple_pair<int, std::string>>::value));
EXPECT_FALSE((absl::is_trivially_copy_constructible<
simple_pair<std::string, int>>::value));
// Verify that arrays are not
using int10 = int[10];
EXPECT_FALSE(absl::is_trivially_copy_constructible<int10>::value);
}
TEST(TypeTraitsTest, TestTrivialMoveAssign) {
// Verify that arithmetic types and pointers have trivial move
// assignment operators.
EXPECT_TRUE(absl::is_trivially_move_assignable<bool>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<char>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<unsigned char>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<signed char>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<wchar_t>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<int>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<unsigned int>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<int16_t>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<uint16_t>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<int64_t>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<uint64_t>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<float>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<double>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<long double>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<std::string*>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial*>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<const std::string*>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<const Trivial*>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<std::string**>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial**>::value);
// const qualified types are not assignable
EXPECT_FALSE(absl::is_trivially_move_assignable<const int>::value);
// types with compiler generated move assignment
EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<TrivialMoveAssign>::value);
// Verify that types without them (i.e. nontrivial or deleted) are not.
EXPECT_FALSE(absl::is_trivially_move_assignable<NontrivialCopyAssign>::value);
EXPECT_FALSE(absl::is_trivially_move_assignable<DeletedCopyAssign>::value);
EXPECT_FALSE(absl::is_trivially_move_assignable<NonCopyableOrMovable>::value);
// types with vtables
EXPECT_FALSE(absl::is_trivially_move_assignable<Base>::value);
// Verify that simple_pair is trivially assignable
EXPECT_TRUE(
(absl::is_trivially_move_assignable<simple_pair<int, char*>>::value));
EXPECT_TRUE(
(absl::is_trivially_move_assignable<simple_pair<int, Trivial>>::value));
EXPECT_TRUE((absl::is_trivially_move_assignable<
simple_pair<int, TrivialMoveAssign>>::value));
// Verify that types not trivially move assignable are
// correctly marked as such.
EXPECT_FALSE(absl::is_trivially_move_assignable<std::string>::value);
EXPECT_FALSE(absl::is_trivially_move_assignable<std::vector<int>>::value);
// Verify that simple_pairs of types not trivially move assignable
// are not marked as trivial.
EXPECT_FALSE((absl::is_trivially_move_assignable<
simple_pair<int, std::string>>::value));
EXPECT_FALSE((absl::is_trivially_move_assignable<
simple_pair<std::string, int>>::value));
// Verify that arrays are not trivially move assignable
using int10 = int[10];
EXPECT_FALSE(absl::is_trivially_move_assignable<int10>::value);
// Verify that references are handled correctly
EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial&&>::value);
EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial&>::value);
}
TEST(TypeTraitsTest, TestTrivialCopyAssign) {
// Verify that arithmetic types and pointers have trivial copy
// assignment operators.
EXPECT_TRUE(absl::is_trivially_copy_assignable<bool>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<char>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<unsigned char>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<signed char>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<wchar_t>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<int>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<unsigned int>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<int16_t>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<uint16_t>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<int64_t>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<uint64_t>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<float>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<double>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<long double>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<std::string*>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial*>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<const std::string*>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<const Trivial*>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<std::string**>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial**>::value);
// const qualified types are not assignable
EXPECT_FALSE(absl::is_trivially_copy_assignable<const int>::value);
// types with compiler generated copy assignment
EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<TrivialCopyAssign>::value);
// Verify that types without them (i.e. nontrivial or deleted) are not.
EXPECT_FALSE(absl::is_trivially_copy_assignable<NontrivialCopyAssign>::value);
EXPECT_FALSE(absl::is_trivially_copy_assignable<DeletedCopyAssign>::value);
EXPECT_FALSE(absl::is_trivially_copy_assignable<MovableNonCopyable>::value);
EXPECT_FALSE(absl::is_trivially_copy_assignable<NonCopyableOrMovable>::value);
// types with vtables
EXPECT_FALSE(absl::is_trivially_copy_assignable<Base>::value);
// Verify that simple_pair is trivially assignable
EXPECT_TRUE(
(absl::is_trivially_copy_assignable<simple_pair<int, char*>>::value));
EXPECT_TRUE(
(absl::is_trivially_copy_assignable<simple_pair<int, Trivial>>::value));
EXPECT_TRUE((absl::is_trivially_copy_assignable<
simple_pair<int, TrivialCopyAssign>>::value));
// Verify that types not trivially copy assignable are
// correctly marked as such.
EXPECT_FALSE(absl::is_trivially_copy_assignable<std::string>::value);
EXPECT_FALSE(absl::is_trivially_copy_assignable<std::vector<int>>::value);
// Verify that simple_pairs of types not trivially copy assignable
// are not marked as trivial.
EXPECT_FALSE((absl::is_trivially_copy_assignable<
simple_pair<int, std::string>>::value));
EXPECT_FALSE((absl::is_trivially_copy_assignable<
simple_pair<std::string, int>>::value));
// Verify that arrays are not trivially copy assignable
using int10 = int[10];
EXPECT_FALSE(absl::is_trivially_copy_assignable<int10>::value);
// Verify that references are handled correctly
EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial&&>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial&>::value);
}
TEST(TypeTraitsTest, TestTriviallyCopyable) {
// Verify that arithmetic types and pointers are trivially copyable.
EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<bool>::value);
EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<char>::value);
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<unsigned char>::value);
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<signed char>::value);
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<wchar_t>::value);
EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<int>::value);
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<unsigned int>::value);
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<int16_t>::value);
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<uint16_t>::value);
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<int64_t>::value);
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<uint64_t>::value);
EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<float>::value);
EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<double>::value);
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<long double>::value);
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<std::string*>::value);
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<Trivial*>::value);
EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<
const std::string*>::value);
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<const Trivial*>::value);
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<std::string**>::value);
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<Trivial**>::value);
// const qualified types are not assignable but are constructible
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<const int>::value);
// Trivial copy constructor/assignment and destructor.
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<Trivial>::value);
// Trivial copy assignment, but non-trivial copy constructor/destructor.
EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
TrivialCopyAssign>::value);
// Trivial copy constructor, but non-trivial assignment.
EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
TrivialCopyCtor>::value);
// Types with a non-trivial copy constructor/assignment
EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
NontrivialCopyCtor>::value);
EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
NontrivialCopyAssign>::value);
// Types without copy constructor/assignment, but with move
// MSVC disagrees with other compilers about this:
// EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<
// MovableNonCopyable>::value);
// Types without copy/move constructor/assignment
EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
NonCopyableOrMovable>::value);
// No copy assign, but has trivial copy constructor.
EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<
DeletedCopyAssign>::value);
// types with vtables
EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<Base>::value);
// Verify that simple_pair is trivially copyable if members are
EXPECT_TRUE((absl::type_traits_internal::is_trivially_copyable<
simple_pair<int, char*>>::value));
EXPECT_TRUE((absl::type_traits_internal::is_trivially_copyable<
simple_pair<int, Trivial>>::value));
// Verify that types not trivially copyable are
// correctly marked as such.
EXPECT_FALSE(
absl::type_traits_internal::is_trivially_copyable<std::string>::value);
EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
std::vector<int>>::value);
// Verify that simple_pairs of types not trivially copyable
// are not marked as trivial.
EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable<
simple_pair<int, std::string>>::value));
EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable<
simple_pair<std::string, int>>::value));
EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable<
simple_pair<int, TrivialCopyAssign>>::value));
// Verify that arrays of trivially copyable types are trivially copyable
using int10 = int[10];
EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<int10>::value);
using int10x10 = int[10][10];
EXPECT_TRUE(
absl::type_traits_internal::is_trivially_copyable<int10x10>::value);
// Verify that references are handled correctly
EXPECT_FALSE(
absl::type_traits_internal::is_trivially_copyable<Trivial&&>::value);
EXPECT_FALSE(
absl::type_traits_internal::is_trivially_copyable<Trivial&>::value);
}
TEST(TypeTraitsTest, TestRemoveCVRef) {
EXPECT_TRUE(
(std::is_same<typename absl::remove_cvref<int>::type, int>::value));
......@@ -1241,82 +662,6 @@ TEST(TypeTraitsTest, TestResultOf) {
EXPECT_EQ(TypeEnum::D, GetTypeExt(Wrap<TypeD>()));
}
template <typename T>
bool TestCopyAssign() {
return absl::is_copy_assignable<T>::value ==
std::is_copy_assignable<T>::value;
}
TEST(TypeTraitsTest, IsCopyAssignable) {
EXPECT_TRUE(TestCopyAssign<int>());
EXPECT_TRUE(TestCopyAssign<int&>());
EXPECT_TRUE(TestCopyAssign<int&&>());
struct S {};
EXPECT_TRUE(TestCopyAssign<S>());
EXPECT_TRUE(TestCopyAssign<S&>());
EXPECT_TRUE(TestCopyAssign<S&&>());
class C {
public:
explicit C(C* c) : c_(c) {}
~C() { delete c_; }
private:
C* c_;
};
EXPECT_TRUE(TestCopyAssign<C>());
EXPECT_TRUE(TestCopyAssign<C&>());
EXPECT_TRUE(TestCopyAssign<C&&>());
// Reason for ifndef: add_lvalue_reference<T> in libc++ breaks for these cases
#ifndef _LIBCPP_VERSION
EXPECT_TRUE(TestCopyAssign<int()>());
EXPECT_TRUE(TestCopyAssign<int(int) const>());
EXPECT_TRUE(TestCopyAssign<int(...) volatile&>());
EXPECT_TRUE(TestCopyAssign<int(int, ...) const volatile&&>());
#endif // _LIBCPP_VERSION
}
template <typename T>
bool TestMoveAssign() {
return absl::is_move_assignable<T>::value ==
std::is_move_assignable<T>::value;
}
TEST(TypeTraitsTest, IsMoveAssignable) {
EXPECT_TRUE(TestMoveAssign<int>());
EXPECT_TRUE(TestMoveAssign<int&>());
EXPECT_TRUE(TestMoveAssign<int&&>());
struct S {};
EXPECT_TRUE(TestMoveAssign<S>());
EXPECT_TRUE(TestMoveAssign<S&>());
EXPECT_TRUE(TestMoveAssign<S&&>());
class C {
public:
explicit C(C* c) : c_(c) {}
~C() { delete c_; }
void operator=(const C&) = delete;
void operator=(C&&) = delete;
private:
C* c_;
};
EXPECT_TRUE(TestMoveAssign<C>());
EXPECT_TRUE(TestMoveAssign<C&>());
EXPECT_TRUE(TestMoveAssign<C&&>());
// Reason for ifndef: add_lvalue_reference<T> in libc++ breaks for these cases
#ifndef _LIBCPP_VERSION
EXPECT_TRUE(TestMoveAssign<int()>());
EXPECT_TRUE(TestMoveAssign<int(int) const>());
EXPECT_TRUE(TestMoveAssign<int(...) volatile&>());
EXPECT_TRUE(TestMoveAssign<int(int, ...) const volatile&&>());
#endif // _LIBCPP_VERSION
}
namespace adl_namespace {
struct DeletedSwap {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment