mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-14 19:49:36 +00:00
[libc++] Add _ITER_CONCEPT and _ITER_TRAITS implementations from C++20
These traits are currently unused because we don't implement ranges. However, their addition is part of ongoing work to allow libc++ to optimize on user-provided contiguous iterators.
This commit is contained in:
parent
45d048c204
commit
6624fcba43
@ -434,6 +434,8 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept;
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
template <class _Iter>
|
||||
struct _LIBCPP_TEMPLATE_VIS iterator_traits;
|
||||
|
||||
struct _LIBCPP_TEMPLATE_VIS input_iterator_tag {};
|
||||
struct _LIBCPP_TEMPLATE_VIS output_iterator_tag {};
|
||||
@ -446,6 +448,52 @@ struct _LIBCPP_TEMPLATE_VIS random_access_iterator_tag : public bidirectional_it
|
||||
struct _LIBCPP_TEMPLATE_VIS contiguous_iterator_tag: public random_access_iterator_tag { };
|
||||
#endif
|
||||
|
||||
template <class _Iter>
|
||||
struct __iter_traits_cache {
|
||||
using type = _If<
|
||||
__is_primary_template<iterator_traits<_Iter> >::value,
|
||||
_Iter,
|
||||
iterator_traits<_Iter>
|
||||
>;
|
||||
};
|
||||
template <class _Iter>
|
||||
using _ITER_TRAITS = typename __iter_traits_cache<_Iter>::type;
|
||||
|
||||
struct __iter_concept_concept_test {
|
||||
template <class _Iter>
|
||||
using _Apply = typename _ITER_TRAITS<_Iter>::iterator_concept;
|
||||
};
|
||||
struct __iter_concept_category_test {
|
||||
template <class _Iter>
|
||||
using _Apply = typename _ITER_TRAITS<_Iter>::iterator_category;
|
||||
};
|
||||
struct __iter_concept_random_fallback {
|
||||
template <class _Iter>
|
||||
using _Apply = _EnableIf<
|
||||
__is_primary_template<iterator_traits<_Iter> >::value,
|
||||
random_access_iterator_tag
|
||||
>;
|
||||
};
|
||||
|
||||
template <class _Iter, class _Tester> struct __test_iter_concept
|
||||
: _IsValidExpansion<_Tester::template _Apply, _Iter>,
|
||||
_Tester
|
||||
{
|
||||
};
|
||||
|
||||
template <class _Iter>
|
||||
struct __iter_concept_cache {
|
||||
using type = _Or<
|
||||
__test_iter_concept<_Iter, __iter_concept_concept_test>,
|
||||
__test_iter_concept<_Iter, __iter_concept_category_test>,
|
||||
__test_iter_concept<_Iter, __iter_concept_random_fallback>
|
||||
>;
|
||||
};
|
||||
|
||||
template <class _Iter>
|
||||
using _ITER_CONCEPT = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>;
|
||||
|
||||
|
||||
template <class _Tp>
|
||||
struct __has_iterator_typedefs
|
||||
{
|
||||
@ -505,7 +553,10 @@ struct __iterator_traits<_Iter, true>
|
||||
|
||||
template <class _Iter>
|
||||
struct _LIBCPP_TEMPLATE_VIS iterator_traits
|
||||
: __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> {};
|
||||
: __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> {
|
||||
|
||||
using __primary_template = iterator_traits;
|
||||
};
|
||||
|
||||
template<class _Tp>
|
||||
struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*>
|
||||
|
@ -525,6 +525,7 @@ struct __identity { typedef _Tp type; };
|
||||
template <class _Tp, bool>
|
||||
struct _LIBCPP_TEMPLATE_VIS __dependent_type : public _Tp {};
|
||||
|
||||
|
||||
template <bool _Bp, class _If, class _Then>
|
||||
struct _LIBCPP_TEMPLATE_VIS conditional {typedef _If type;};
|
||||
template <class _If, class _Then>
|
||||
@ -570,6 +571,16 @@ using _IsNotSame = _BoolConstant<
|
||||
#endif
|
||||
>;
|
||||
|
||||
|
||||
template <class _Tp>
|
||||
using __test_for_primary_template = _EnableIf<
|
||||
_IsSame<_Tp, typename _Tp::__primary_template>::value
|
||||
>;
|
||||
template <class _Tp>
|
||||
using __is_primary_template = _IsValidExpansion<
|
||||
__test_for_primary_template, _Tp
|
||||
>;
|
||||
|
||||
// addressof
|
||||
#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
|
||||
|
||||
|
@ -0,0 +1,73 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03
|
||||
|
||||
// ITER_TRAITS(I)
|
||||
|
||||
// -- If the qualified-id ITER_TRAITS(I)::iterator_concept is valid and names a
|
||||
// type, then ITER_CONCEPT(I) denotes that type.
|
||||
// (1.2) -- Otherwise, if the qualified-id ITER_TRAITS(I)::iterator_category is
|
||||
// valid and names a type, then ITER_CONCEPT(I) denotes that type.
|
||||
// (1.3) -- Otherwise, if iterator_traits<I> names a specialization generated
|
||||
// from the primary template, then ITER_CONCEPT(I) denotes
|
||||
// random_access_iterator_tag.
|
||||
// (1.4) -- Otherwise, ITER_CONCEPT(I) does not denote a type.
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#include <iterator>
|
||||
struct OtherTag : std::input_iterator_tag {};
|
||||
struct OtherTagTwo : std::output_iterator_tag {};
|
||||
struct MyIter : std::iterator<std::random_access_iterator_tag, char> {
|
||||
using iterator_concept = int;
|
||||
};
|
||||
struct MyIter2 : std::iterator<OtherTag, char> {
|
||||
|
||||
};
|
||||
struct MyIter3 {};
|
||||
|
||||
struct Empty {};
|
||||
struct EmptyWithSpecial {};
|
||||
namespace std {
|
||||
template <>
|
||||
struct iterator_traits<MyIter3>
|
||||
: std::iterator<OtherTagTwo, char> {};
|
||||
|
||||
template <>
|
||||
struct iterator_traits<EmptyWithSpecial> {
|
||||
// empty non-default.
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
int main(int, char**) {
|
||||
// If the qualified-id ITER_TRAITS(I)::iterator_concept is valid and names a type,
|
||||
// then ITER_CONCEPT(I) denotes that type.
|
||||
{
|
||||
#if TEST_STD_VER > 17
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<char*>, std::contiguous_iterator_tag);
|
||||
#endif
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<MyIter>, int);
|
||||
}
|
||||
// Otherwise, if the qualified-id ITER_TRAITS(I)::iterator_category is valid
|
||||
// and names a type, then ITER_CONCEPT(I) denotes that type.
|
||||
{
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<MyIter2>, OtherTag);
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<MyIter3>, OtherTagTwo);
|
||||
}
|
||||
// FIXME - This requirement makes no sense to me. Why does an empty type with
|
||||
// an empty default iterator_traits get a category of random?
|
||||
{
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<Empty>, std::random_access_iterator_tag);
|
||||
}
|
||||
{
|
||||
static_assert(!std::_IsValidExpansion<std::_ITER_CONCEPT, EmptyWithSpecial>::value, "");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03
|
||||
|
||||
// ITER_TRAITS(I)
|
||||
|
||||
// For a type I, let ITER_TRAITS(I) denote the type I if iterator_traits<I> names
|
||||
// a specialization generated from the primary template. Otherwise,
|
||||
// ITER_TRAITS(I) denotes iterator_traits<I>.
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#include <iterator>
|
||||
|
||||
struct MyIter : std::iterator<std::random_access_iterator_tag, char> {};
|
||||
struct MyIter2 : std::iterator<std::random_access_iterator_tag, char> {};
|
||||
struct MyIter3 : std::iterator<std::random_access_iterator_tag, char> {};
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct iterator_traits<MyIter>
|
||||
: iterator_traits<std::iterator<std::random_access_iterator_tag, char> > {};
|
||||
template <>
|
||||
struct iterator_traits<MyIter2>
|
||||
: std::iterator<std::random_access_iterator_tag, char> {};
|
||||
|
||||
} // namespace std
|
||||
|
||||
int main(int, char**) {
|
||||
ASSERT_SAME_TYPE(std::_ITER_TRAITS<char*>, std::iterator_traits<char*>);
|
||||
{
|
||||
using ClassIter = std::reverse_iterator<char*>;
|
||||
ASSERT_SAME_TYPE(std::_ITER_TRAITS<ClassIter>, ClassIter);
|
||||
ASSERT_SAME_TYPE(std::_ITER_TRAITS<MyIter3>, MyIter3);
|
||||
}
|
||||
{
|
||||
ASSERT_SAME_TYPE(std::_ITER_TRAITS<MyIter>, std::iterator_traits<MyIter>);
|
||||
ASSERT_SAME_TYPE(std::_ITER_TRAITS<MyIter2>, std::iterator_traits<MyIter2>);
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user