Add std::variant specializations for IsOwner and IsView Fixes: #1960 PiperOrigin-RevId: 951017341 Change-Id: If8de7073695152947aa93e0d5a3800dac6e353b6
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h index be55e52..d12300f 100644 --- a/absl/meta/type_traits.h +++ b/absl/meta/type_traits.h
@@ -41,6 +41,7 @@ #include <string_view> #include <type_traits> #include <utility> +#include <variant> #include <vector> #include "absl/base/attributes.h" @@ -583,6 +584,14 @@ template <typename T, typename Alloc> struct IsOwner<std::vector<T, Alloc>> : std::true_type {}; +template <typename... T> +struct IsOwner<std::variant<T...>> + : std::bool_constant<(sizeof...(T) > 0) && + // Uses a C++17 fold expression where '...' unpacks the + // parameter pack T, and 'true &&' provides the base + // case for the logical AND operation across all types. + (true && ... && IsOwner<T>::value)> {}; + // Detects if a class's definition has declared itself to be a view by declaring // using absl_internal_is_view = std::true_type; // as a member. @@ -620,6 +629,14 @@ template <typename Char, typename Traits> struct IsView<std::basic_string_view<Char, Traits>> : std::true_type {}; +template <typename... T> +struct IsView<std::variant<T...>> + : std::bool_constant<(sizeof...(T) > 0) && + // Uses a C++17 fold expression where '...' unpacks the + // parameter pack T, and 'true &&' provides the base + // case for the logical AND operation across all types. + (true && ... && IsView<T>::value)> {}; + #ifdef __cpp_lib_span template <typename T> struct IsView<std::span<T>> : std::true_type {};
diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc index 9734fc1..8e5f90d 100644 --- a/absl/meta/type_traits_test.cc +++ b/absl/meta/type_traits_test.cc
@@ -19,6 +19,7 @@ #include <string_view> #include <type_traits> #include <utility> +#include <variant> #include <vector> #include "gtest/gtest.h" @@ -32,6 +33,11 @@ using ::testing::StaticAssertTypeEq; template <typename T> +using IsViewAndNotOwner = + std::conjunction<absl::type_traits_internal::IsView<T>, + std::negation<absl::type_traits_internal::IsOwner<T>>>; + +template <typename T> using IsOwnerAndNotView = std::conjunction<absl::type_traits_internal::IsOwner<T>, std::negation<absl::type_traits_internal::IsView<T>>>; @@ -50,6 +56,23 @@ static_assert(!IsOwnerAndNotView<std::wstring_view>::value, "wstring_view is a view, not an owner"); +static_assert(!IsOwnerAndNotView<std::variant<>>::value, + "empty variant is not an owner"); +static_assert(!IsViewAndNotOwner<std::variant<>>::value, + "empty variant is not a view"); + +static_assert(IsOwnerAndNotView<std::variant<std::string, std::vector<char>, + std::vector<int>>>::value, + "aggregate of owners is an owner"); +static_assert( + IsViewAndNotOwner<std::variant<std::wstring_view, std::string_view>>::value, + "aggregate of views is an view"); + +static_assert(!IsOwnerAndNotView<std::variant<const char*, std::string>>::value, + "variant of mixed-ownership types is not considered an owner"); +static_assert(!IsViewAndNotOwner<std::variant<const char*, std::string>>::value, + "variant of mixed-ownership types is not considered a view"); + template <class T, class U> struct simple_pair { T first;