diff options
Diffstat (limited to 'absl/strings/internal')
-rw-r--r-- | absl/strings/internal/stl_type_traits.h | 213 | ||||
-rw-r--r-- | absl/strings/internal/str_split_internal.h | 24 |
2 files changed, 223 insertions, 14 deletions
diff --git a/absl/strings/internal/stl_type_traits.h b/absl/strings/internal/stl_type_traits.h new file mode 100644 index 000000000000..8c3d877e6356 --- /dev/null +++ b/absl/strings/internal/stl_type_traits.h @@ -0,0 +1,213 @@ +// 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. +// + +// 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 { +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 must have three partial specializations, +// because we must only compare templates that take the same number of +// arguments. Otherwise, for example, std::vector can be compared with std::map, +// and fail to compile because of too few or too many template arguments. +// +// We must also SFINAE on the existence of an allocator_type. Otherwise, we may +// try to compare, for example, a std::pair<std::string, std::string> with a +// std::vector<std::string, std:std::string>. This would fail to compile, because +// of expected properties of the type passed in as the allocator. +template <template <typename, typename> class U, + template <typename, typename> class T, typename... Args> +struct IsBaseOfSpecializationImpl< + U<Args...>, T, absl::void_t<typename U<Args...>::allocator_type>> + : std::is_base_of<U<Args...>, T<Args...>> {}; +template <template <typename, typename, typename> class U, + template <typename, typename, typename> class T, typename... Args> +struct IsBaseOfSpecializationImpl< + U<Args...>, T, absl::void_t<typename U<Args...>::allocator_type>> + : std::is_base_of<U<Args...>, T<Args...>> {}; +template <template <typename, typename, typename, typename> class U, + template <typename, typename, typename, typename> class T, + typename... Args> +struct IsBaseOfSpecializationImpl< + U<Args...>, T, absl::void_t<typename U<Args...>::allocator_type>> + : std::is_base_of<U<Args...>, T<Args...>> {}; +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 must have three partial specializations, +// because we must only compare templates that take the same number of +// arguments. Otherwise, for example, std::vector can be compared with std::map, +// and fail to compile because of too few or too many template arguments. +// +// We must also SFINAE on the existence of an allocator_type. Otherwise, we may +// try to compare, for example, a std::pair<std::string, std::string> with a +// std::vector<std::string, std:std::string>. This would fail to compile, because +// of expected properties of the type passed in as the allocator. +template <template <typename, typename> class U, + template <typename, typename> class T, typename... Args> +struct IsConvertibleToSpecializationImpl< + U<Args...>, T, absl::void_t<typename U<Args...>::allocator_type>> + : std::is_convertible<U<Args...>, T<Args...>> {}; +template <template <typename, typename, typename> class U, + template <typename, typename, typename> class T, typename... Args> +struct IsConvertibleToSpecializationImpl< + U<Args...>, T, absl::void_t<typename U<Args...>::allocator_type>> + : std::is_convertible<U<Args...>, T<Args...>> {}; +template <template <typename, typename, typename, typename> class U, + template <typename, typename, typename, typename> class T, + typename... Args> +struct IsConvertibleToSpecializationImpl< + U<Args...>, T, absl::void_t<typename U<Args...>::allocator_type>> + : std::is_convertible<U<Args...>, T<Args...>> {}; +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 +} // namespace absl +#endif // ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_ diff --git a/absl/strings/internal/str_split_internal.h b/absl/strings/internal/str_split_internal.h index dc31a8ef9090..a1b10f3addcf 100644 --- a/absl/strings/internal/str_split_internal.h +++ b/absl/strings/internal/str_split_internal.h @@ -29,10 +29,6 @@ #ifndef ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_ #define ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_ -#ifdef _GLIBCXX_DEBUG -#include <glibcxx_debug_traits.h> -#endif // _GLIBCXX_DEBUG - #include <array> #include <initializer_list> #include <iterator> @@ -46,15 +42,13 @@ #include "absl/meta/type_traits.h" #include "absl/strings/string_view.h" -namespace absl { -namespace strings_internal { - #ifdef _GLIBCXX_DEBUG -using ::glibcxx_debug_traits::IsStrictlyDebugWrapperBase; -#else // _GLIBCXX_DEBUG -template <typename T> struct IsStrictlyDebugWrapperBase : std::false_type {}; +#include "absl/strings/internal/stl_type_traits.h" #endif // _GLIBCXX_DEBUG +namespace absl { +namespace strings_internal { + // This class is implicitly constructible from everything that absl::string_view // is implicitly constructible from. If it's constructed from a temporary // std::string, the data is moved into a data member so its lifetime matches that of @@ -237,10 +231,12 @@ struct IsInitializerList template <typename C> struct SplitterIsConvertibleTo : std::enable_if< - !IsStrictlyDebugWrapperBase<C>::value && - !IsInitializerList<C>::value && - HasValueType<C>::value && - HasConstIterator<C>::value> {}; +#ifdef _GLIBCXX_DEBUG + !IsStrictlyBaseOfAndConvertibleToSTLContainer<C>::value && +#endif // _GLIBCXX_DEBUG + !IsInitializerList<C>::value && HasValueType<C>::value && + HasConstIterator<C>::value> { +}; // This class implements the range that is returned by absl::StrSplit(). This // class has templated conversion operators that allow it to be implicitly |