From c2e754829628d1e9b7a16b3389cfdace76950fdf Mon Sep 17 00:00:00 2001 From: misterg Date: Tue, 19 Sep 2017 16:54:40 -0400 Subject: Initial Commit --- absl/meta/BUILD.bazel | 29 ++ absl/meta/type_traits.h | 314 +++++++++++++++++++++ absl/meta/type_traits_test.cc | 640 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 983 insertions(+) create mode 100644 absl/meta/BUILD.bazel create mode 100644 absl/meta/type_traits.h create mode 100644 absl/meta/type_traits_test.cc (limited to 'absl/meta') diff --git a/absl/meta/BUILD.bazel b/absl/meta/BUILD.bazel new file mode 100644 index 0000000..872751e --- /dev/null +++ b/absl/meta/BUILD.bazel @@ -0,0 +1,29 @@ +load( + "//absl:copts.bzl", + "ABSL_DEFAULT_COPTS", + "ABSL_TEST_COPTS", +) + +package(default_visibility = ["//visibility:public"]) + +licenses(["unencumbered"]) # Owned by Google + +cc_library( + name = "type_traits", + hdrs = ["type_traits.h"], + copts = ABSL_DEFAULT_COPTS, + deps = [ + "//absl/base:config", + ], +) + +cc_test( + name = "type_traits_test", + srcs = ["type_traits_test.cc"], + copts = ABSL_TEST_COPTS, + deps = [ + ":type_traits", + "//absl/base:core_headers", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h new file mode 100644 index 0000000..779afd2 --- /dev/null +++ b/absl/meta/type_traits.h @@ -0,0 +1,314 @@ +// +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// type_traits.h +// ----------------------------------------------------------------------------- +// +// This file contains C++11-compatible versions of standard API +// functions for determining the characteristics of types. Such traits can +// support type inference, classification, and transformation, as well as +// make it easier to write templates based on generic type behavior. +// +// See http://en.cppreference.com/w/cpp/header/type_traits +// +// WARNING: use of many of the constructs in this header will count as "complex +// template metaprogramming", so before proceeding, please carefully consider +// https://google.github.io/styleguide/cppguide.html#Template_metaprogramming +// +// WARNING: using template metaprogramming to detect or depend on API +// features is brittle and not guaranteed. Neither the standard library nor +// Abseil provides any guarantee that APIs are stable in the face of template +// metaprogramming. Use with caution. +#ifndef ABSL_META_TYPE_TRAITS_H_ +#define ABSL_META_TYPE_TRAITS_H_ + +#include + +#include "absl/base/config.h" + +namespace absl { + +namespace type_traits_internal { +template +struct VoidTImpl { + using type = void; +}; + +// This trick to retrieve a default alignment is necessary for our +// implementation of aligned_storage_t to be consistent with any implementation +// of std::aligned_storage. +template > +struct default_alignment_of_aligned_storage; + +template +struct default_alignment_of_aligned_storage> { + static constexpr size_t value = Align; +}; + +} // namespace type_traits_internal + +// void_t() +// +// Ignores the type of any its arguments and returns `void`. In general, this +// metafunction allows you to create a general case that maps to `void` while +// allowing specializations that map to specific types. +// +// This metafunction is designed to be a drop-in replacement for the C++17 +// `std::void_t` metafunction. +// +// NOTE: `absl::void_t` does not use the standard-specified implementation so +// that it can remain compatibile with gcc < 5.1. This can introduce slightly +// different behavior, such as when ordering partial specializations. +template +using void_t = typename type_traits_internal::VoidTImpl::type; + +// conjunction +// +// Performs a compile-time logical AND operation on the passed types (which +// must have `::value` members convertible to `bool`. Short-circuits if it +// encounters any `false` members (and does not compare the `::value` members +// of any remaining arguments). +// +// This metafunction is designed to be a drop-in replacement for the C++17 +// `std::conjunction` metafunction. +template +struct conjunction; + +template +struct conjunction + : std::conditional, T>::type {}; + +template +struct conjunction : T {}; + +template <> +struct conjunction<> : std::true_type {}; + +// disjunction +// +// Performs a compile-time logical OR operation on the passed types (which +// must have `::value` members convertible to `bool`. Short-circuits if it +// encounters any `true` members (and does not compare the `::value` members +// of any remaining arguments). +// +// This metafunction is designed to be a drop-in replacement for the C++17 +// `std::disjunction` metafunction. +template +struct disjunction; + +template +struct disjunction : + std::conditional>::type {}; + +template +struct disjunction : T {}; + +template <> +struct disjunction<> : std::false_type {}; + +// negation +// +// Performs a compile-time logical NOT operation on the passed type (which +// must have `::value` members convertible to `bool`. +// +// This metafunction is designed to be a drop-in replacement for the C++17 +// `std::negation` metafunction. +template +struct negation : std::integral_constant {}; + +// is_trivially_destructible() +// +// Determines whether the passed type `T` is trivially destructable. +// +// This metafunction is designed to be a drop-in replacement for the C++17 +// `std::is_trivially_destructible()` metafunction. +// +// 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 +struct is_trivially_destructible + : std::integral_constant::value> { +#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE + static_assert(std::is_trivially_destructible::value == + is_trivially_destructible::value, + "Not compliant with std::is_trivially_destructible"); +#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++17 +// `std::is_trivially_default_constructible()` metafunction. +// +// NOTE: according to the C++ standard, Section: 20.15.4.3 [meta.unary.prop] +// "The predicate condition for a template specialization is_constructible shall be satisfied if and only if the following variable +// definition would be well-formed for some invented variable t: +// +// T t(declval()...); +// +// is_trivially_constructible 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 http://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 non-trivial operation. +// Nontrivally destructible types will cause the expression to be nontrivial. +template +struct is_trivially_default_constructible + : std::integral_constant::value && + is_trivially_destructible::value> { +#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE + static_assert(std::is_trivially_default_constructible::value == + is_trivially_default_constructible::value, + "Not compliant with std::is_trivially_default_constructible"); +#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++17 +// `std::is_trivially_copy_constructible()` metafunction. +// +// NOTE: `T obj(declval());` needs to be well-formed and not call any +// nontrivial operation. Nontrivally destructible types will cause the +// expression to be nontrivial. +template +struct is_trivially_copy_constructible + : std::integral_constant::value && + is_trivially_destructible::value> { +#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE + static_assert(std::is_trivially_copy_constructible::value == + is_trivially_copy_constructible::value, + "Not compliant with std::is_trivially_copy_constructible"); +#endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE +}; + +// 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++17 +// `std::is_trivially_copy_assignable()` metafunction. +// +// NOTE: `is_assignable::value` is `true` if the expression +// `declval() = declval()` is well-formed when treated as an unevaluated +// operand. `is_trivially_assignable` requires the assignment to call no +// operation that is not trivial. `is_trivially_copy_assignable` is simply +// `is_trivially_assignable`. +template +struct is_trivially_copy_assignable + : std::integral_constant::value> { +#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE + static_assert(std::is_trivially_copy_assignable::value == + is_trivially_copy_assignable::value, + "Not compliant with std::is_trivially_copy_assignable"); +#endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE +}; + +// ----------------------------------------------------------------------------- +// C++14 "_t" trait aliases +// ----------------------------------------------------------------------------- + +template +using remove_cv_t = typename std::remove_cv::type; + +template +using remove_const_t = typename std::remove_const::type; + +template +using remove_volatile_t = typename std::remove_volatile::type; + +template +using add_cv_t = typename std::add_cv::type; + +template +using add_const_t = typename std::add_const::type; + +template +using add_volatile_t = typename std::add_volatile::type; + +template +using remove_reference_t = typename std::remove_reference::type; + +template +using add_lvalue_reference_t = typename std::add_lvalue_reference::type; + +template +using add_rvalue_reference_t = typename std::add_rvalue_reference::type; + +template +using remove_pointer_t = typename std::remove_pointer::type; + +template +using add_pointer_t = typename std::add_pointer::type; + +template +using make_signed_t = typename std::make_signed::type; + +template +using make_unsigned_t = typename std::make_unsigned::type; + +template +using remove_extent_t = typename std::remove_extent::type; + +template +using remove_all_extents_t = typename std::remove_all_extents::type; + +template ::value> +using aligned_storage_t = typename std::aligned_storage::type; + +template +using decay_t = typename std::decay::type; + +template +using enable_if_t = typename std::enable_if::type; + +template +using conditional_t = typename std::conditional::type; + +template +using common_type_t = typename std::common_type::type; + +template +using underlying_type_t = typename std::underlying_type::type; + +template +using result_of_t = typename std::result_of::type; + +} // namespace absl +#endif // ABSL_META_TYPE_TRAITS_H_ diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc new file mode 100644 index 0000000..54dcc8f --- /dev/null +++ b/absl/meta/type_traits_test.cc @@ -0,0 +1,640 @@ +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/meta/type_traits.h" + +#include +#include +#include +#include + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace { + +using ::testing::StaticAssertTypeEq; + +struct Dummy {}; + +TEST(VoidTTest, BasicUsage) { + StaticAssertTypeEq>(); + StaticAssertTypeEq>(); +} + +TEST(ConjunctionTest, BasicBooleanLogic) { + EXPECT_TRUE(absl::conjunction<>::value); + EXPECT_TRUE(absl::conjunction::value); + EXPECT_TRUE((absl::conjunction::value)); + EXPECT_FALSE((absl::conjunction::value)); + EXPECT_FALSE((absl::conjunction::value)); + EXPECT_FALSE((absl::conjunction::value)); +} + +struct MyTrueType { + static constexpr bool value = true; +}; + +struct MyFalseType { + static constexpr bool value = false; +}; + +TEST(ConjunctionTest, ShortCircuiting) { + EXPECT_FALSE( + (absl::conjunction::value)); + EXPECT_TRUE((std::is_base_of>::value)); + EXPECT_TRUE( + (std::is_base_of>::value)); +} + +TEST(DisjunctionTest, BasicBooleanLogic) { + EXPECT_FALSE(absl::disjunction<>::value); + EXPECT_FALSE(absl::disjunction::value); + EXPECT_TRUE((absl::disjunction::value)); + EXPECT_TRUE((absl::disjunction::value)); + EXPECT_TRUE((absl::disjunction::value)); + EXPECT_FALSE((absl::disjunction::value)); +} + +TEST(DisjunctionTest, ShortCircuiting) { + EXPECT_TRUE( + (absl::disjunction::value)); + EXPECT_TRUE(( + std::is_base_of>::value)); + EXPECT_TRUE(( + std::is_base_of>::value)); +} + +TEST(NegationTest, BasicBooleanLogic) { + EXPECT_FALSE(absl::negation::value); + EXPECT_FALSE(absl::negation::value); + EXPECT_TRUE(absl::negation::value); + EXPECT_TRUE(absl::negation::value); +} + +// all member functions are trivial +class Trivial { + int n_; +}; + +class TrivialDefaultCtor { + public: + TrivialDefaultCtor() = default; + explicit TrivialDefaultCtor(int n) : n_(n) {} + + private: + int n_; +}; + +class TrivialCopyCtor { + public: + explicit TrivialCopyCtor(int n) : n_(n) {} + TrivialCopyCtor(const TrivialCopyCtor&) = default; + TrivialCopyCtor& operator=(const TrivialCopyCtor& t) { + n_ = t.n_; + return *this; + } + + private: + int n_; +}; + +class TrivialCopyAssign { + public: + explicit TrivialCopyAssign(int n) : n_(n) {} + TrivialCopyAssign(const TrivialCopyAssign& t) : n_(t.n_) {} + TrivialCopyAssign& operator=(const TrivialCopyAssign& t) = default; + ~TrivialCopyAssign() {} // can have non trivial destructor + private: + int n_; +}; + +struct NonTrivialDestructor { + ~NonTrivialDestructor() {} +}; + +struct TrivialDestructor { + ~TrivialDestructor() = default; +}; + +struct NonCopyable { + NonCopyable() = default; + NonCopyable(const NonCopyable&) = delete; + NonCopyable& operator=(const NonCopyable&) = delete; +}; + +class Base { + public: + virtual ~Base() {} +}; + +// In GCC/Clang, std::is_trivially_constructible requires that the destructor is +// trivial. However, MSVC doesn't require that. This results in different +// behavior when checking is_trivially_constructible on any type with nontrivial +// destructor. Since absl::is_trivially_default_constructible and +// absl::is_trivially_copy_constructible both follows Clang/GCC's interpretation +// and check is_trivially_destructible, it results in inconsistency with +// std::is_trivially_xxx_constructible on MSVC. This macro is used to work +// around this issue in test. In practice, a trivially constructible type +// should also be trivially destructible. +// 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. +#ifdef _MSC_VER +#define ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE +#endif + +TEST(TypeTraitsTest, TestTrivialDefaultCtor) { + // arithmetic types and pointers have trivial default constructors. + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE( + absl::is_trivially_default_constructible::value); + EXPECT_TRUE( + absl::is_trivially_default_constructible::value); + + // types with compiler generated default ctors + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE( + absl::is_trivially_default_constructible::value); + +#ifndef ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE + // types with non trivial destructor are non trivial + EXPECT_FALSE( + absl::is_trivially_default_constructible::value); +#endif + + // types with vtables + EXPECT_FALSE(absl::is_trivially_default_constructible::value); + + // Verify that arrays of such types are trivially default constructible + typedef int int10[10]; + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + typedef Trivial Trivial10[10]; + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + typedef Trivial TrivialDefaultCtor10[10]; + EXPECT_TRUE( + absl::is_trivially_default_constructible::value); + + // Verify that std::pair has non-trivial constructors. + EXPECT_FALSE( + (absl::is_trivially_default_constructible>::value)); + + // Verify that types without trivial constructors are + // correctly marked as such. + EXPECT_FALSE(absl::is_trivially_default_constructible::value); + EXPECT_FALSE( + absl::is_trivially_default_constructible>::value); +} + +TEST(TypeTraitsTest, TestTrivialCopyCtor) { + // Verify that arithmetic types and pointers have trivial copy + // constructors. + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE( + absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + + // types with compiler generated copy ctors + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + +#ifndef ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE + // type with non-trivial destructor are non-trivial copy construbtible + EXPECT_FALSE( + absl::is_trivially_copy_constructible::value); +#endif + + // types with vtables + EXPECT_FALSE(absl::is_trivially_copy_constructible::value); + + // Verify that std pair of such types is trivially copy constructible + EXPECT_TRUE( + (absl::is_trivially_copy_constructible>::value)); + EXPECT_TRUE( + (absl::is_trivially_copy_constructible>::value)); + EXPECT_TRUE((absl::is_trivially_copy_constructible< + std::pair>::value)); + + // Verify that arrays are not + typedef int int10[10]; + EXPECT_FALSE(absl::is_trivially_copy_constructible::value); + + // Verify that pairs of types without trivial copy constructors + // are not marked as trivial. + EXPECT_FALSE((absl::is_trivially_copy_constructible< + std::pair>::value)); + EXPECT_FALSE((absl::is_trivially_copy_constructible< + std::pair>::value)); + + // Verify that types without trivial copy constructors are + // correctly marked as such. + EXPECT_FALSE(absl::is_trivially_copy_constructible::value); + EXPECT_FALSE(absl::is_trivially_copy_constructible>::value); + + // types with deleted copy constructors are not copy constructible + EXPECT_FALSE(absl::is_trivially_copy_constructible::value); +} + +TEST(TypeTraitsTest, TestTrivialCopyAssign) { + // Verify that arithmetic types and pointers have trivial copy + // constructors. + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE( + absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + + // const qualified types are not assignable + EXPECT_FALSE(absl::is_trivially_copy_assignable::value); + + // types with compiler generated copy assignment + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable::value); + + // types with vtables + EXPECT_FALSE(absl::is_trivially_copy_assignable::value); + + // Verify that arrays are not trivially copy assignable + typedef int int10[10]; + EXPECT_FALSE(absl::is_trivially_copy_assignable::value); + + // Verify that std::pair is not trivially assignable + EXPECT_FALSE( + (absl::is_trivially_copy_assignable>::value)); + + // Verify that types without trivial copy constructors are + // correctly marked as such. + EXPECT_FALSE(absl::is_trivially_copy_assignable::value); + EXPECT_FALSE(absl::is_trivially_copy_assignable>::value); + + // types with deleted copy assignment are not copy assignable + EXPECT_FALSE(absl::is_trivially_copy_assignable::value); +} + +TEST(TypeTraitsTest, TestTrivialDestructor) { + // Verify that arithmetic types and pointers have trivial copy + // constructors. + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + + // classes with destructors + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); + EXPECT_FALSE(absl::is_trivially_destructible::value); + + // std::pair of such types is trivial + EXPECT_TRUE((absl::is_trivially_destructible>::value)); + EXPECT_TRUE((absl::is_trivially_destructible< + std::pair>::value)); + + // array of such types is trivial + typedef int int10[10]; + EXPECT_TRUE(absl::is_trivially_destructible::value); + typedef TrivialDestructor TrivialDestructor10[10]; + EXPECT_TRUE(absl::is_trivially_destructible::value); + typedef NonTrivialDestructor NonTrivialDestructor10[10]; + EXPECT_FALSE(absl::is_trivially_destructible::value); +} + +#define ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(trait_name, ...) \ + EXPECT_TRUE((std::is_same::type, \ + absl::trait_name##_t<__VA_ARGS__>>::value)) + +TEST(TypeTraitsTest, TestRemoveCVAliases) { + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_cv, int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_cv, const int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_cv, volatile int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_cv, const volatile int); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_const, int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_const, const int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_const, volatile int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_const, const volatile int); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_volatile, int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_volatile, const int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_volatile, volatile int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_volatile, const volatile int); +} + +TEST(TypeTraitsTest, TestAddCVAliases) { + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_cv, int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_cv, const int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_cv, volatile int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_cv, const volatile int); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_const, int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_const, const int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_const, volatile int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_const, const volatile int); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_volatile, int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_volatile, const int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_volatile, volatile int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_volatile, const volatile int); +} + +TEST(TypeTraitsTest, TestReferenceAliases) { + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, volatile int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, int&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, volatile int&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, int&&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, volatile int&&); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, volatile int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, int&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, volatile int&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, int&&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, volatile int&&); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, volatile int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, int&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, volatile int&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, int&&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, volatile int&&); +} + +TEST(TypeTraitsTest, TestPointerAliases) { + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_pointer, int*); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_pointer, volatile int*); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_pointer, int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_pointer, volatile int); +} + +TEST(TypeTraitsTest, TestSignednessAliases) { + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_signed, int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_signed, volatile int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_signed, unsigned); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_signed, volatile unsigned); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_unsigned, int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_unsigned, volatile int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_unsigned, unsigned); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_unsigned, volatile unsigned); +} + +TEST(TypeTraitsTest, TestExtentAliases) { + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_extent, int[]); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_extent, int[1]); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_extent, int[1][1]); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_extent, int[][1]); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_all_extents, int[]); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_all_extents, int[1]); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_all_extents, int[1][1]); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_all_extents, int[][1]); +} + +TEST(TypeTraitsTest, TestAlignedStorageAlias) { + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 1); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 2); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 3); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 4); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 5); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 6); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 7); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 8); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 9); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 10); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 11); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 12); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 13); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 14); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 15); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 16); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 17); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 18); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 19); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 20); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 21); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 22); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 23); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 24); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 25); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 26); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 27); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 28); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 29); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 30); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 31); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 32); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 33); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 1, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 2, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 3, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 4, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 5, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 6, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 7, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 8, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 9, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 10, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 11, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 12, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 13, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 14, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 15, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 16, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 17, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 18, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 19, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 20, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 21, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 22, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 23, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 24, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 25, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 26, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 27, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 28, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 29, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 30, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 31, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 32, 128); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 33, 128); +} + +TEST(TypeTraitsTest, TestDecay) { + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, volatile int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const volatile int); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const int&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, volatile int&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const volatile int&); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const int&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, volatile int&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const volatile int&); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int[1]); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int[1][1]); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int[][1]); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int()); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int(float)); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int(char, ...)); +} + +struct TypeA {}; +struct TypeB {}; +struct TypeC {}; +struct TypeD {}; + +template +struct Wrap {}; + +enum class TypeEnum { A, B, C, D }; + +struct GetTypeT { + template ::value, int> = 0> + TypeEnum operator()(Wrap) const { + return TypeEnum::A; + } + + template ::value, int> = 0> + TypeEnum operator()(Wrap) const { + return TypeEnum::B; + } + + template ::value, int> = 0> + TypeEnum operator()(Wrap) const { + return TypeEnum::C; + } + + // NOTE: TypeD is intentionally not handled +} constexpr GetType = {}; + +TEST(TypeTraitsTest, TestEnableIf) { + EXPECT_EQ(TypeEnum::A, GetType(Wrap())); + EXPECT_EQ(TypeEnum::B, GetType(Wrap())); + EXPECT_EQ(TypeEnum::C, GetType(Wrap())); +} + +TEST(TypeTraitsTest, TestConditional) { + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(conditional, true, int, char); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(conditional, false, int, char); +} + +// TODO(calabrese) Check with specialized std::common_type +TEST(TypeTraitsTest, TestCommonType) { + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int, char); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int, char, int); + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int, char&); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int, char, int&); +} + +TEST(TypeTraitsTest, TestUnderlyingType) { + enum class enum_char : char {}; + enum class enum_long_long : long long {}; // NOLINT(runtime/int) + + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(underlying_type, enum_char); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(underlying_type, enum_long_long); +} + +struct GetTypeExtT { + template + absl::result_of_t operator()(T&& arg) const { + return GetType(std::forward(arg)); + } + + TypeEnum operator()(Wrap) const { return TypeEnum::D; } +} constexpr GetTypeExt = {}; + +TEST(TypeTraitsTest, TestResultOf) { + EXPECT_EQ(TypeEnum::A, GetTypeExt(Wrap())); + EXPECT_EQ(TypeEnum::B, GetTypeExt(Wrap())); + EXPECT_EQ(TypeEnum::C, GetTypeExt(Wrap())); + EXPECT_EQ(TypeEnum::D, GetTypeExt(Wrap())); +} + +} // namespace -- cgit v1.2.3