// 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 // // https://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. // // Thie file provides the IsStrictlyBaseOfAndConvertibleToSTLContainer type // trait metafunction to assist in working with the _GLIBCXX_DEBUG debug // wrappers of STL containers. // // DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including // absl/strings/str_split.h. // // IWYU pragma: private, include "absl/strings/str_split.h" #ifndef ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_ #define ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_ #include <array> #include <bitset> #include <deque> #include <forward_list> #include <list> #include <map> #include <set> #include <type_traits> #include <unordered_map> #include <unordered_set> #include <vector> #include "absl/meta/type_traits.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace strings_internal { template <typename C, template <typename...> class T> struct IsSpecializationImpl : std::false_type {}; template <template <typename...> class T, typename... Args> struct IsSpecializationImpl<T<Args...>, T> : std::true_type {}; template <typename C, template <typename...> class T> using IsSpecialization = IsSpecializationImpl<absl::decay_t<C>, T>; template <typename C> struct IsArrayImpl : std::false_type {}; template <template <typename, size_t> class A, typename T, size_t N> struct IsArrayImpl<A<T, N>> : std::is_same<A<T, N>, std::array<T, N>> {}; template <typename C> using IsArray = IsArrayImpl<absl::decay_t<C>>; template <typename C> struct IsBitsetImpl : std::false_type {}; template <template <size_t> class B, size_t N> struct IsBitsetImpl<B<N>> : std::is_same<B<N>, std::bitset<N>> {}; template <typename C> using IsBitset = IsBitsetImpl<absl::decay_t<C>>; template <typename C> struct IsSTLContainer : absl::disjunction< IsArray<C>, IsBitset<C>, IsSpecialization<C, std::deque>, IsSpecialization<C, std::forward_list>, IsSpecialization<C, std::list>, IsSpecialization<C, std::map>, IsSpecialization<C, std::multimap>, IsSpecialization<C, std::set>, IsSpecialization<C, std::multiset>, IsSpecialization<C, std::unordered_map>, IsSpecialization<C, std::unordered_multimap>, IsSpecialization<C, std::unordered_set>, IsSpecialization<C, std::unordered_multiset>, IsSpecialization<C, std::vector>> {}; template <typename C, template <typename...> class T, typename = void> struct IsBaseOfSpecializationImpl : std::false_type {}; // IsBaseOfSpecializationImpl needs multiple partial specializations to SFINAE // on the existence of container dependent types and plug them into the STL // template. template <typename C, template <typename, typename> class T> struct IsBaseOfSpecializationImpl< C, T, absl::void_t<typename C::value_type, typename C::allocator_type>> : std::is_base_of<C, T<typename C::value_type, typename C::allocator_type>> {}; template <typename C, template <typename, typename, typename> class T> struct IsBaseOfSpecializationImpl< C, T, absl::void_t<typename C::key_type, typename C::key_compare, typename C::allocator_type>> : std::is_base_of<C, T<typename C::key_type, typename C::key_compare, typename C::allocator_type>> {}; template <typename C, template <typename, typename, typename, typename> class T> struct IsBaseOfSpecializationImpl< C, T, absl::void_t<typename C::key_type, typename C::mapped_type, typename C::key_compare, typename C::allocator_type>> : std::is_base_of<C, T<typename C::key_type, typename C::mapped_type, typename C::key_compare, typename C::allocator_type>> { }; template <typename C, template <typename, typename, typename, typename> class T> struct IsBaseOfSpecializationImpl< C, T, absl::void_t<typename C::key_type, typename C::hasher, typename C::key_equal, typename C::allocator_type>> : std::is_base_of<C, T<typename C::key_type, typename C::hasher, typename C::key_equal, typename C::allocator_type>> { }; template <typename C, template <typename, typename, typename, typename, typename> class T> struct IsBaseOfSpecializationImpl< C, T, absl::void_t<typename C::key_type, typename C::mapped_type, typename C::hasher, typename C::key_equal, typename C::allocator_type>> : std::is_base_of<C, T<typename C::key_type, typename C::mapped_type, typename C::hasher, typename C::key_equal, typename C::allocator_type>> {}; template <typename C, template <typename...> class T> using IsBaseOfSpecialization = IsBaseOfSpecializationImpl<absl::decay_t<C>, T>; template <typename C> struct IsBaseOfArrayImpl : std::false_type {}; template <template <typename, size_t> class A, typename T, size_t N> struct IsBaseOfArrayImpl<A<T, N>> : std::is_base_of<A<T, N>, std::array<T, N>> { }; template <typename C> using IsBaseOfArray = IsBaseOfArrayImpl<absl::decay_t<C>>; template <typename C> struct IsBaseOfBitsetImpl : std::false_type {}; template <template <size_t> class B, size_t N> struct IsBaseOfBitsetImpl<B<N>> : std::is_base_of<B<N>, std::bitset<N>> {}; template <typename C> using IsBaseOfBitset = IsBaseOfBitsetImpl<absl::decay_t<C>>; template <typename C> struct IsBaseOfSTLContainer : absl::disjunction<IsBaseOfArray<C>, IsBaseOfBitset<C>, IsBaseOfSpecialization<C, std::deque>, IsBaseOfSpecialization<C, std::forward_list>, IsBaseOfSpecialization<C, std::list>, IsBaseOfSpecialization<C, std::map>, IsBaseOfSpecialization<C, std::multimap>, IsBaseOfSpecialization<C, std::set>, IsBaseOfSpecialization<C, std::multiset>, IsBaseOfSpecialization<C, std::unordered_map>, IsBaseOfSpecialization<C, std::unordered_multimap>, IsBaseOfSpecialization<C, std::unordered_set>, IsBaseOfSpecialization<C, std::unordered_multiset>, IsBaseOfSpecialization<C, std::vector>> {}; template <typename C, template <typename...> class T, typename = void> struct IsConvertibleToSpecializationImpl : std::false_type {}; // IsConvertibleToSpecializationImpl needs multiple partial specializations to // SFINAE on the existence of container dependent types and plug them into the // STL template. template <typename C, template <typename, typename> class T> struct IsConvertibleToSpecializationImpl< C, T, absl::void_t<typename C::value_type, typename C::allocator_type>> : std::is_convertible< C, T<typename C::value_type, typename C::allocator_type>> {}; template <typename C, template <typename, typename, typename> class T> struct IsConvertibleToSpecializationImpl< C, T, absl::void_t<typename C::key_type, typename C::key_compare, typename C::allocator_type>> : std::is_convertible<C, T<typename C::key_type, typename C::key_compare, typename C::allocator_type>> {}; template <typename C, template <typename, typename, typename, typename> class T> struct IsConvertibleToSpecializationImpl< C, T, absl::void_t<typename C::key_type, typename C::mapped_type, typename C::key_compare, typename C::allocator_type>> : std::is_convertible< C, T<typename C::key_type, typename C::mapped_type, typename C::key_compare, typename C::allocator_type>> {}; template <typename C, template <typename, typename, typename, typename> class T> struct IsConvertibleToSpecializationImpl< C, T, absl::void_t<typename C::key_type, typename C::hasher, typename C::key_equal, typename C::allocator_type>> : std::is_convertible< C, T<typename C::key_type, typename C::hasher, typename C::key_equal, typename C::allocator_type>> {}; template <typename C, template <typename, typename, typename, typename, typename> class T> struct IsConvertibleToSpecializationImpl< C, T, absl::void_t<typename C::key_type, typename C::mapped_type, typename C::hasher, typename C::key_equal, typename C::allocator_type>> : std::is_convertible<C, T<typename C::key_type, typename C::mapped_type, typename C::hasher, typename C::key_equal, typename C::allocator_type>> {}; template <typename C, template <typename...> class T> using IsConvertibleToSpecialization = IsConvertibleToSpecializationImpl<absl::decay_t<C>, T>; template <typename C> struct IsConvertibleToArrayImpl : std::false_type {}; template <template <typename, size_t> class A, typename T, size_t N> struct IsConvertibleToArrayImpl<A<T, N>> : std::is_convertible<A<T, N>, std::array<T, N>> {}; template <typename C> using IsConvertibleToArray = IsConvertibleToArrayImpl<absl::decay_t<C>>; template <typename C> struct IsConvertibleToBitsetImpl : std::false_type {}; template <template <size_t> class B, size_t N> struct IsConvertibleToBitsetImpl<B<N>> : std::is_convertible<B<N>, std::bitset<N>> {}; template <typename C> using IsConvertibleToBitset = IsConvertibleToBitsetImpl<absl::decay_t<C>>; template <typename C> struct IsConvertibleToSTLContainer : absl::disjunction< IsConvertibleToArray<C>, IsConvertibleToBitset<C>, IsConvertibleToSpecialization<C, std::deque>, IsConvertibleToSpecialization<C, std::forward_list>, IsConvertibleToSpecialization<C, std::list>, IsConvertibleToSpecialization<C, std::map>, IsConvertibleToSpecialization<C, std::multimap>, IsConvertibleToSpecialization<C, std::set>, IsConvertibleToSpecialization<C, std::multiset>, IsConvertibleToSpecialization<C, std::unordered_map>, IsConvertibleToSpecialization<C, std::unordered_multimap>, IsConvertibleToSpecialization<C, std::unordered_set>, IsConvertibleToSpecialization<C, std::unordered_multiset>, IsConvertibleToSpecialization<C, std::vector>> {}; template <typename C> struct IsStrictlyBaseOfAndConvertibleToSTLContainer : absl::conjunction<absl::negation<IsSTLContainer<C>>, IsBaseOfSTLContainer<C>, IsConvertibleToSTLContainer<C>> {}; } // namespace strings_internal ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_