forked from OSchip/llvm-project
[libc++] Add all indirect callable concepts and projected
Differential Revision: https://reviews.llvm.org/D101277
This commit is contained in:
parent
2b9b9652ce
commit
58b29a4efc
|
@ -17,10 +17,12 @@ set(files
|
|||
__iterator/advance.h
|
||||
__iterator/concepts.h
|
||||
__iterator/incrementable_traits.h
|
||||
__iterator/indirect_concepts.h
|
||||
__iterator/iter_move.h
|
||||
__iterator/iterator_traits.h
|
||||
__iterator/next.h
|
||||
__iterator/prev.h
|
||||
__iterator/projected.h
|
||||
__iterator/readable_traits.h
|
||||
__libcpp_version
|
||||
__locale
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <__iterator/readable_traits.h>
|
||||
#include <__memory/pointer_traits.h>
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
|
@ -48,6 +49,9 @@ concept __indirectly_readable_impl =
|
|||
template<class _In>
|
||||
concept indirectly_readable = __indirectly_readable_impl<remove_cvref_t<_In> >;
|
||||
|
||||
template<indirectly_readable _Tp>
|
||||
using iter_common_reference_t = common_reference_t<iter_reference_t<_Tp>, iter_value_t<_Tp>&>;
|
||||
|
||||
// [iterator.concept.writable]
|
||||
template<class _Out, class _Tp>
|
||||
concept indirectly_writable =
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP___ITERATOR_INDIRECT_CONCEPTS_H
|
||||
#define _LIBCPP___ITERATOR_INDIRECT_CONCEPTS_H
|
||||
|
||||
#include <__config>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <__iterator/incrementable_traits.h>
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_RANGES)
|
||||
|
||||
template<class _Fp, class _It>
|
||||
concept indirectly_unary_invocable =
|
||||
indirectly_readable<_It> &&
|
||||
copy_constructible<_Fp> &&
|
||||
invocable<_Fp&, iter_value_t<_It>&> &&
|
||||
invocable<_Fp&, iter_reference_t<_It>> &&
|
||||
invocable<_Fp&, iter_common_reference_t<_It>> &&
|
||||
common_reference_with<
|
||||
invoke_result_t<_Fp&, iter_value_t<_It>&>,
|
||||
invoke_result_t<_Fp&, iter_reference_t<_It>>>;
|
||||
|
||||
template<class _Fp, class _It>
|
||||
concept indirectly_regular_unary_invocable =
|
||||
indirectly_readable<_It> &&
|
||||
copy_constructible<_Fp> &&
|
||||
regular_invocable<_Fp&, iter_value_t<_It>&> &&
|
||||
regular_invocable<_Fp&, iter_reference_t<_It>> &&
|
||||
regular_invocable<_Fp&, iter_common_reference_t<_It>> &&
|
||||
common_reference_with<
|
||||
invoke_result_t<_Fp&, iter_value_t<_It>&>,
|
||||
invoke_result_t<_Fp&, iter_reference_t<_It>>>;
|
||||
|
||||
template<class _Fp, class _It>
|
||||
concept indirect_unary_predicate =
|
||||
indirectly_readable<_It> &&
|
||||
copy_constructible<_Fp> &&
|
||||
predicate<_Fp&, iter_value_t<_It>&> &&
|
||||
predicate<_Fp&, iter_reference_t<_It>> &&
|
||||
predicate<_Fp&, iter_common_reference_t<_It>>;
|
||||
|
||||
template<class _Fp, class _It1, class _It2>
|
||||
concept indirect_binary_predicate =
|
||||
indirectly_readable<_It1> && indirectly_readable<_It2> &&
|
||||
copy_constructible<_Fp> &&
|
||||
predicate<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> &&
|
||||
predicate<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> &&
|
||||
predicate<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> &&
|
||||
predicate<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>> &&
|
||||
predicate<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>;
|
||||
|
||||
template<class _Fp, class _It1, class _It2 = _It1>
|
||||
concept indirect_equivalence_relation =
|
||||
indirectly_readable<_It1> && indirectly_readable<_It2> &&
|
||||
copy_constructible<_Fp> &&
|
||||
equivalence_relation<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> &&
|
||||
equivalence_relation<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> &&
|
||||
equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> &&
|
||||
equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>> &&
|
||||
equivalence_relation<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>;
|
||||
|
||||
template<class _Fp, class _It1, class _It2 = _It1>
|
||||
concept indirect_strict_weak_order =
|
||||
indirectly_readable<_It1> && indirectly_readable<_It2> &&
|
||||
copy_constructible<_Fp> &&
|
||||
strict_weak_order<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> &&
|
||||
strict_weak_order<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> &&
|
||||
strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> &&
|
||||
strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>> &&
|
||||
strict_weak_order<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>;
|
||||
|
||||
template<class _Fp, class... _Its>
|
||||
requires (indirectly_readable<_Its> && ...) && invocable<_Fp, iter_reference_t<_Its>...>
|
||||
using indirect_result_t = invoke_result_t<_Fp, iter_reference_t<_Its>...>;
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___ITERATOR_INDIRECT_CONCEPTS_H
|
|
@ -0,0 +1,46 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP___ITERATOR_PROJECTED_H
|
||||
#define _LIBCPP___ITERATOR_PROJECTED_H
|
||||
|
||||
#include <__config>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <__iterator/indirect_concepts.h>
|
||||
#include <__iterator/incrementable_traits.h>
|
||||
#include <type_traits>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_RANGES)
|
||||
|
||||
template<indirectly_readable _It, indirectly_regular_unary_invocable<_It> _Proj>
|
||||
struct projected {
|
||||
using value_type = remove_cvref_t<indirect_result_t<_Proj&, _It>>;
|
||||
indirect_result_t<_Proj&, _It> operator*() const; // not defined
|
||||
};
|
||||
|
||||
template<weakly_incrementable _It, class _Proj>
|
||||
struct incrementable_traits<projected<_It, _Proj>> {
|
||||
using difference_type = iter_difference_t<_It>;
|
||||
};
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___ITERATOR_PROJECTED_H
|
|
@ -46,7 +46,11 @@ using iter_rvalue_reference_t = decltype(ranges::iter_move(declval<T&>())); // s
|
|||
// [iterator.concepts], iterator concepts
|
||||
// [iterator.concept.readable], concept indirectly_readable
|
||||
template<class In>
|
||||
concept indirectly_readable = see below; // since C++20
|
||||
concept indirectly_readable = see below; // since C++20
|
||||
|
||||
template<indirectly_readable T>
|
||||
using iter_common_reference_t =
|
||||
common_reference_t<iter_reference_t<T>, iter_value_t<T>&>; // since C++20
|
||||
|
||||
// [iterator.concept.writable], concept indirectly_writable
|
||||
template<class Out, class T>
|
||||
|
@ -91,6 +95,36 @@ template<class I>
|
|||
template<class I>
|
||||
concept random_access_iterator = see below; // since C++20
|
||||
|
||||
// [indirectcallable]
|
||||
// [indirectcallable.indirectinvocable]
|
||||
template<class F, class I>
|
||||
concept indirectly_unary_invocable = see below; // since C++20
|
||||
|
||||
template<class F, class I>
|
||||
concept indirectly_regular_unary_invocable = see below; // since C++20
|
||||
|
||||
template<class F, class I>
|
||||
concept indirect_unary_predicate = see below; // since C++20
|
||||
|
||||
template<class F, class I1, class I2>
|
||||
concept indirect_binary_predicate = see below; // since C++20
|
||||
|
||||
template<class F, class I1, class I2 = I1>
|
||||
concept indirect_equivalence_relation = see below; // since C++20
|
||||
|
||||
template<class F, class I1, class I2 = I1>
|
||||
concept indirect_strict_weak_order = see below; // since C++20
|
||||
|
||||
template<class F, class... Is>
|
||||
using indirect_result_t = see below; // since C++20
|
||||
|
||||
// [projected], projected
|
||||
template<indirectly_readable I, indirectly_regular_unary_invocable<I> Proj>
|
||||
struct projected; // since C++20
|
||||
|
||||
template<weakly_incrementable I, indirectly_regular_unary_invocable<I> Proj>
|
||||
struct incrementable_traits<projected<I, Proj>>; // since C++20
|
||||
|
||||
template<class Category, class T, class Distance = ptrdiff_t,
|
||||
class Pointer = T*, class Reference = T&>
|
||||
struct iterator // deprecated in C++17
|
||||
|
@ -486,10 +520,12 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept;
|
|||
#include <__iterator/advance.h>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <__iterator/incrementable_traits.h>
|
||||
#include <__iterator/indirect_concepts.h>
|
||||
#include <__iterator/iter_move.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__iterator/next.h>
|
||||
#include <__iterator/prev.h>
|
||||
#include <__iterator/projected.h>
|
||||
#include <__iterator/readable_traits.h>
|
||||
#include <__memory/addressof.h>
|
||||
#include <__memory/pointer_traits.h>
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
// UNSUPPORTED: gcc-10
|
||||
|
||||
// template<class F, class I1, class I2>
|
||||
// concept indirect_binary_predicate;
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#include "indirectly_readable.h"
|
||||
|
||||
using It1 = IndirectlyReadable<struct Token1>;
|
||||
using It2 = IndirectlyReadable<struct Token2>;
|
||||
|
||||
template <class I1, class I2>
|
||||
struct GoodPredicate {
|
||||
bool operator()(std::iter_value_t<I1>&, std::iter_value_t<I2>&) const;
|
||||
bool operator()(std::iter_value_t<I1>&, std::iter_reference_t<I2>) const;
|
||||
bool operator()(std::iter_reference_t<I1>, std::iter_value_t<I2>&) const;
|
||||
bool operator()(std::iter_reference_t<I1>, std::iter_reference_t<I2>) const;
|
||||
bool operator()(std::iter_common_reference_t<I1>, std::iter_common_reference_t<I2>) const;
|
||||
};
|
||||
|
||||
// Should work when all constraints are satisfied
|
||||
static_assert(std::indirect_binary_predicate<GoodPredicate<It1, It2>, It1, It2>);
|
||||
static_assert(std::indirect_binary_predicate<bool(*)(int, float), int*, float*>);
|
||||
[[maybe_unused]] auto lambda = [](int i, int j) { return i < j; };
|
||||
static_assert(std::indirect_binary_predicate<decltype(lambda), int*, int*>);
|
||||
|
||||
// Should fail when either of the iterators is not indirectly_readable
|
||||
struct NotIndirectlyReadable { };
|
||||
static_assert(!std::indirect_binary_predicate<GoodPredicate<It1, NotIndirectlyReadable>, It1, NotIndirectlyReadable>);
|
||||
static_assert(!std::indirect_binary_predicate<GoodPredicate<NotIndirectlyReadable, It2>, NotIndirectlyReadable, It2>);
|
||||
|
||||
// Should fail when the predicate is not copy constructible
|
||||
struct BadPredicate1 {
|
||||
BadPredicate1(BadPredicate1 const&) = delete;
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
};
|
||||
static_assert(!std::indirect_binary_predicate<BadPredicate1, It1, It2>);
|
||||
|
||||
// Should fail when the predicate can't be called with (iter_value_t&, iter_value_t&)
|
||||
struct BadPredicate2 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_value_t<It1>&, std::iter_value_t<It2>&) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_binary_predicate<BadPredicate2, It1, It2>);
|
||||
|
||||
// Should fail when the predicate can't be called with (iter_value_t&, iter_reference_t)
|
||||
struct BadPredicate3 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_value_t<It1>&, std::iter_reference_t<It2>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_binary_predicate<BadPredicate3, It1, It2>);
|
||||
|
||||
// Should fail when the predicate can't be called with (iter_reference_t, iter_value_t&)
|
||||
struct BadPredicate4 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_reference_t<It1>, std::iter_value_t<It2>&) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_binary_predicate<BadPredicate4, It1, It2>);
|
||||
|
||||
// Should fail when the predicate can't be called with (iter_reference_t, iter_reference_t)
|
||||
struct BadPredicate5 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_reference_t<It1>, std::iter_reference_t<It2>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_binary_predicate<BadPredicate5, It1, It2>);
|
||||
|
||||
// Should fail when the predicate can't be called with (iter_common_reference_t, iter_common_reference_t)
|
||||
struct BadPredicate6 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_common_reference_t<It1>, std::iter_common_reference_t<It2>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_binary_predicate<BadPredicate6, It1, It2>);
|
|
@ -0,0 +1,99 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
// UNSUPPORTED: gcc-10
|
||||
|
||||
// template<class F, class I1, class I2 = I1>
|
||||
// concept indirect_equivalence_relation;
|
||||
|
||||
#include <iterator>
|
||||
#include <concepts>
|
||||
|
||||
#include "indirectly_readable.h"
|
||||
|
||||
using It1 = IndirectlyReadable<struct Token1>;
|
||||
using It2 = IndirectlyReadable<struct Token2>;
|
||||
|
||||
template <class I1, class I2>
|
||||
struct GoodRelation {
|
||||
bool operator()(std::iter_value_t<I1>&, std::iter_value_t<I1>&) const;
|
||||
bool operator()(std::iter_value_t<I2>&, std::iter_value_t<I2>&) const;
|
||||
bool operator()(std::iter_value_t<I1>&, std::iter_value_t<I2>&) const;
|
||||
bool operator()(std::iter_value_t<I2>&, std::iter_value_t<I1>&) const;
|
||||
|
||||
bool operator()(std::iter_value_t<I1>&, std::iter_reference_t<I2>) const;
|
||||
bool operator()(std::iter_reference_t<I2>, std::iter_value_t<I1>&) const;
|
||||
bool operator()(std::iter_reference_t<I2>, std::iter_reference_t<I2>) const;
|
||||
|
||||
bool operator()(std::iter_reference_t<I1>, std::iter_value_t<I2>&) const;
|
||||
bool operator()(std::iter_value_t<I2>&, std::iter_reference_t<I1>) const;
|
||||
bool operator()(std::iter_reference_t<I1>, std::iter_reference_t<I1>) const;
|
||||
|
||||
bool operator()(std::iter_reference_t<I1>, std::iter_reference_t<I2>) const;
|
||||
bool operator()(std::iter_reference_t<I2>, std::iter_reference_t<I1>) const;
|
||||
|
||||
bool operator()(std::iter_common_reference_t<I1>, std::iter_common_reference_t<I1>) const;
|
||||
bool operator()(std::iter_common_reference_t<I2>, std::iter_common_reference_t<I2>) const;
|
||||
bool operator()(std::iter_common_reference_t<I1>, std::iter_common_reference_t<I2>) const;
|
||||
bool operator()(std::iter_common_reference_t<I2>, std::iter_common_reference_t<I1>) const;
|
||||
};
|
||||
|
||||
// Should work when all constraints are satisfied
|
||||
static_assert(std::indirect_equivalence_relation<GoodRelation<It1, It2>, It1, It2>);
|
||||
static_assert(std::indirect_equivalence_relation<bool(*)(int, long), int*, long*>);
|
||||
[[maybe_unused]] auto lambda = [](int i, long j) { return i == j; };
|
||||
static_assert(std::indirect_equivalence_relation<decltype(lambda), int*, long*>);
|
||||
|
||||
// Should fail when either of the iterators is not indirectly_readable
|
||||
struct NotIndirectlyReadable { };
|
||||
static_assert(!std::indirect_equivalence_relation<GoodRelation<It1, NotIndirectlyReadable>, It1, NotIndirectlyReadable>);
|
||||
static_assert(!std::indirect_equivalence_relation<GoodRelation<NotIndirectlyReadable, It2>, NotIndirectlyReadable, It2>);
|
||||
|
||||
// Should fail when the function is not copy constructible
|
||||
struct BadRelation1 {
|
||||
BadRelation1(BadRelation1 const&) = delete;
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
};
|
||||
static_assert(!std::indirect_equivalence_relation<BadRelation1, It1, It2>);
|
||||
|
||||
// Should fail when the function can't be called with (iter_value_t&, iter_value_t&)
|
||||
struct BadRelation2 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_value_t<It1>&, std::iter_value_t<It2>&) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_equivalence_relation<BadRelation2, It1, It2>);
|
||||
|
||||
// Should fail when the function can't be called with (iter_value_t&, iter_reference_t)
|
||||
struct BadRelation3 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_value_t<It1>&, std::iter_reference_t<It2>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_equivalence_relation<BadRelation3, It1, It2>);
|
||||
|
||||
// Should fail when the function can't be called with (iter_reference_t, iter_value_t&)
|
||||
struct BadRelation4 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_reference_t<It1>, std::iter_value_t<It2>&) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_equivalence_relation<BadRelation4, It1, It2>);
|
||||
|
||||
// Should fail when the function can't be called with (iter_reference_t, iter_reference_t)
|
||||
struct BadRelation5 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_reference_t<It1>, std::iter_reference_t<It2>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_equivalence_relation<BadRelation5, It1, It2>);
|
||||
|
||||
// Should fail when the function can't be called with (iter_common_reference_t, iter_common_reference_t)
|
||||
struct BadRelation6 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_common_reference_t<It1>, std::iter_common_reference_t<It2>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_equivalence_relation<BadRelation6, It1, It2>);
|
|
@ -0,0 +1,33 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
// UNSUPPORTED: gcc-10
|
||||
|
||||
// indirect_result_t
|
||||
|
||||
#include <iterator>
|
||||
#include <concepts>
|
||||
|
||||
static_assert(std::same_as<std::indirect_result_t<int (*)(int), int*>, int>);
|
||||
static_assert(std::same_as<std::indirect_result_t<double (*)(int const&, float), int const*, float*>, double>);
|
||||
|
||||
struct S { };
|
||||
static_assert(std::same_as<std::indirect_result_t<S (&)(int), int*>, S>);
|
||||
static_assert(std::same_as<std::indirect_result_t<long S::*, S*>, long&>);
|
||||
static_assert(std::same_as<std::indirect_result_t<S && (S::*)(), S*>, S&&>);
|
||||
static_assert(std::same_as<std::indirect_result_t<int S::* (S::*)(int) const, S*, int*>, int S::*>);
|
||||
|
||||
template <class F, class... Is>
|
||||
constexpr bool has_indirect_result = requires {
|
||||
typename std::indirect_result_t<F, Is...>;
|
||||
};
|
||||
|
||||
static_assert(!has_indirect_result<int (*)(int), int>); // int isn't indirectly_readable
|
||||
static_assert(!has_indirect_result<int, int*>); // int isn't invocable
|
|
@ -0,0 +1,99 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
// UNSUPPORTED: gcc-10
|
||||
|
||||
// template<class F, class I1, class I2 = I1>
|
||||
// concept indirect_strict_weak_order;
|
||||
|
||||
#include <iterator>
|
||||
#include <concepts>
|
||||
|
||||
#include "indirectly_readable.h"
|
||||
|
||||
using It1 = IndirectlyReadable<struct Token1>;
|
||||
using It2 = IndirectlyReadable<struct Token2>;
|
||||
|
||||
template <class I1, class I2>
|
||||
struct GoodOrder {
|
||||
bool operator()(std::iter_value_t<I1>&, std::iter_value_t<I1>&) const;
|
||||
bool operator()(std::iter_value_t<I2>&, std::iter_value_t<I2>&) const;
|
||||
bool operator()(std::iter_value_t<I1>&, std::iter_value_t<I2>&) const;
|
||||
bool operator()(std::iter_value_t<I2>&, std::iter_value_t<I1>&) const;
|
||||
|
||||
bool operator()(std::iter_value_t<I1>&, std::iter_reference_t<I2>) const;
|
||||
bool operator()(std::iter_reference_t<I2>, std::iter_value_t<I1>&) const;
|
||||
bool operator()(std::iter_reference_t<I2>, std::iter_reference_t<I2>) const;
|
||||
|
||||
bool operator()(std::iter_reference_t<I1>, std::iter_value_t<I2>&) const;
|
||||
bool operator()(std::iter_value_t<I2>&, std::iter_reference_t<I1>) const;
|
||||
bool operator()(std::iter_reference_t<I1>, std::iter_reference_t<I1>) const;
|
||||
|
||||
bool operator()(std::iter_reference_t<I1>, std::iter_reference_t<I2>) const;
|
||||
bool operator()(std::iter_reference_t<I2>, std::iter_reference_t<I1>) const;
|
||||
|
||||
bool operator()(std::iter_common_reference_t<I1>, std::iter_common_reference_t<I1>) const;
|
||||
bool operator()(std::iter_common_reference_t<I2>, std::iter_common_reference_t<I2>) const;
|
||||
bool operator()(std::iter_common_reference_t<I1>, std::iter_common_reference_t<I2>) const;
|
||||
bool operator()(std::iter_common_reference_t<I2>, std::iter_common_reference_t<I1>) const;
|
||||
};
|
||||
|
||||
// Should work when all constraints are satisfied
|
||||
static_assert(std::indirect_strict_weak_order<GoodOrder<It1, It2>, It1, It2>);
|
||||
static_assert(std::indirect_strict_weak_order<bool(*)(int, long), int*, long*>);
|
||||
[[maybe_unused]] auto lambda = [](int i, long j) { return i < j; };
|
||||
static_assert(std::indirect_strict_weak_order<decltype(lambda), int*, long*>);
|
||||
|
||||
// Should fail when either of the iterators is not indirectly_readable
|
||||
struct NotIndirectlyReadable { };
|
||||
static_assert(!std::indirect_strict_weak_order<GoodOrder<It1, NotIndirectlyReadable>, It1, NotIndirectlyReadable>);
|
||||
static_assert(!std::indirect_strict_weak_order<GoodOrder<NotIndirectlyReadable, It2>, NotIndirectlyReadable, It2>);
|
||||
|
||||
// Should fail when the function is not copy constructible
|
||||
struct BadOrder1 {
|
||||
BadOrder1(BadOrder1 const&) = delete;
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
};
|
||||
static_assert(!std::indirect_strict_weak_order<BadOrder1, It1, It2>);
|
||||
|
||||
// Should fail when the function can't be called with (iter_value_t&, iter_value_t&)
|
||||
struct BadOrder2 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_value_t<It1>&, std::iter_value_t<It2>&) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_strict_weak_order<BadOrder2, It1, It2>);
|
||||
|
||||
// Should fail when the function can't be called with (iter_value_t&, iter_reference_t)
|
||||
struct BadOrder3 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_value_t<It1>&, std::iter_reference_t<It2>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_strict_weak_order<BadOrder3, It1, It2>);
|
||||
|
||||
// Should fail when the function can't be called with (iter_reference_t, iter_value_t&)
|
||||
struct BadOrder4 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_reference_t<It1>, std::iter_value_t<It2>&) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_strict_weak_order<BadOrder4, It1, It2>);
|
||||
|
||||
// Should fail when the function can't be called with (iter_reference_t, iter_reference_t)
|
||||
struct BadOrder5 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_reference_t<It1>, std::iter_reference_t<It2>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_strict_weak_order<BadOrder5, It1, It2>);
|
||||
|
||||
// Should fail when the function can't be called with (iter_common_reference_t, iter_common_reference_t)
|
||||
struct BadOrder6 {
|
||||
template <class T, class U> bool operator()(T const&, U const&) const;
|
||||
bool operator()(std::iter_common_reference_t<It1>, std::iter_common_reference_t<It2>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_strict_weak_order<BadOrder6, It1, It2>);
|
|
@ -0,0 +1,66 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
// UNSUPPORTED: gcc-10
|
||||
|
||||
// template<class F, class I>
|
||||
// concept indirect_unary_predicate;
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#include "indirectly_readable.h"
|
||||
|
||||
using It = IndirectlyReadable<struct Token>;
|
||||
|
||||
template <class I>
|
||||
struct GoodPredicate {
|
||||
bool operator()(std::iter_reference_t<I>) const;
|
||||
bool operator()(std::iter_value_t<I>&) const;
|
||||
bool operator()(std::iter_common_reference_t<I>) const;
|
||||
};
|
||||
|
||||
// Should work when all constraints are satisfied
|
||||
static_assert(std::indirect_unary_predicate<GoodPredicate<It>, It>);
|
||||
static_assert(std::indirect_unary_predicate<bool(*)(int), int*>);
|
||||
[[maybe_unused]] auto lambda = [](int i) { return i % 2 == 0; };
|
||||
static_assert(std::indirect_unary_predicate<decltype(lambda), int*>);
|
||||
|
||||
// Should fail when the iterator is not indirectly_readable
|
||||
struct NotIndirectlyReadable { };
|
||||
static_assert(!std::indirect_unary_predicate<GoodPredicate<NotIndirectlyReadable>, NotIndirectlyReadable>);
|
||||
|
||||
// Should fail when the predicate is not copy constructible
|
||||
struct BadPredicate1 {
|
||||
BadPredicate1(BadPredicate1 const&) = delete;
|
||||
template <class T> bool operator()(T const&) const;
|
||||
};
|
||||
static_assert(!std::indirect_unary_predicate<BadPredicate1, It>);
|
||||
|
||||
// Should fail when the predicate can't be called with std::iter_value_t<It>&
|
||||
struct BadPredicate2 {
|
||||
template <class T> bool operator()(T const&) const;
|
||||
bool operator()(std::iter_value_t<It>&) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_unary_predicate<BadPredicate2, It>);
|
||||
|
||||
// Should fail when the predicate can't be called with std::iter_reference_t<It>
|
||||
struct BadPredicate3 {
|
||||
template <class T> bool operator()(T const&) const;
|
||||
bool operator()(std::iter_reference_t<It>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_unary_predicate<BadPredicate3, It>);
|
||||
|
||||
// Should fail when the predicate can't be called with std::iter_common_reference_t<It>
|
||||
struct BadPredicate4 {
|
||||
template <class T> bool operator()(T const&) const;
|
||||
bool operator()(std::iter_common_reference_t<It>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirect_unary_predicate<BadPredicate4, It>);
|
|
@ -0,0 +1,89 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
// UNSUPPORTED: gcc-10
|
||||
|
||||
// template<class F, class I>
|
||||
// concept indirectly_regular_unary_invocable;
|
||||
|
||||
#include <iterator>
|
||||
#include <concepts>
|
||||
|
||||
#include "indirectly_readable.h"
|
||||
|
||||
using It = IndirectlyReadable<struct Token>;
|
||||
using R1 = T1<struct ReturnToken>;
|
||||
using R2 = T2<struct ReturnToken>;
|
||||
|
||||
template <class I>
|
||||
struct GoodInvocable {
|
||||
R1 operator()(std::iter_value_t<I>&) const;
|
||||
R2 operator()(std::iter_reference_t<I>) const;
|
||||
R2 operator()(std::iter_common_reference_t<I>) const;
|
||||
};
|
||||
|
||||
// Should work when all constraints are satisfied
|
||||
static_assert(std::indirectly_regular_unary_invocable<GoodInvocable<It>, It>);
|
||||
|
||||
// Should fail when the iterator is not indirectly_readable
|
||||
struct NotIndirectlyReadable { };
|
||||
static_assert(!std::indirectly_regular_unary_invocable<GoodInvocable<NotIndirectlyReadable>, NotIndirectlyReadable>);
|
||||
|
||||
// Should fail when the invocable is not copy constructible
|
||||
struct BadInvocable1 {
|
||||
BadInvocable1(BadInvocable1 const&) = delete;
|
||||
template <class T> R1 operator()(T const&) const;
|
||||
};
|
||||
static_assert(!std::indirectly_regular_unary_invocable<BadInvocable1, It>);
|
||||
|
||||
// Should fail when the invocable can't be called with (iter_value_t&)
|
||||
struct BadInvocable2 {
|
||||
template <class T> R1 operator()(T const&) const;
|
||||
R1 operator()(std::iter_value_t<It>&) const = delete;
|
||||
};
|
||||
static_assert(!std::indirectly_regular_unary_invocable<BadInvocable2, It>);
|
||||
|
||||
// Should fail when the invocable can't be called with (iter_reference_t)
|
||||
struct BadInvocable3 {
|
||||
template <class T> R1 operator()(T const&) const;
|
||||
R1 operator()(std::iter_reference_t<It>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirectly_regular_unary_invocable<BadInvocable3, It>);
|
||||
|
||||
// Should fail when the invocable can't be called with (iter_common_reference_t)
|
||||
struct BadInvocable4 {
|
||||
template <class T> R1 operator()(T const&) const;
|
||||
R1 operator()(std::iter_common_reference_t<It>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirectly_regular_unary_invocable<BadInvocable4, It>);
|
||||
|
||||
// Should fail when the invocable doesn't have a common reference between its return types
|
||||
struct BadInvocable5 {
|
||||
R1 operator()(std::iter_value_t<It>&) const;
|
||||
struct Unrelated { };
|
||||
Unrelated operator()(std::iter_reference_t<It>) const;
|
||||
R1 operator()(std::iter_common_reference_t<It>) const;
|
||||
};
|
||||
static_assert(!std::indirectly_regular_unary_invocable<BadInvocable5, It>);
|
||||
|
||||
// Various tests with callables
|
||||
struct S;
|
||||
static_assert(std::indirectly_regular_unary_invocable<int (*)(int), int*>);
|
||||
static_assert(std::indirectly_regular_unary_invocable<int (&)(int), int*>);
|
||||
static_assert(std::indirectly_regular_unary_invocable<int S::*, S*>);
|
||||
static_assert(std::indirectly_regular_unary_invocable<int (S::*)(), S*>);
|
||||
static_assert(std::indirectly_regular_unary_invocable<int (S::*)() const, S*>);
|
||||
static_assert(std::indirectly_regular_unary_invocable<void(*)(int), int*>);
|
||||
|
||||
static_assert(!std::indirectly_regular_unary_invocable<int(int), int*>); // not move constructible
|
||||
static_assert(!std::indirectly_regular_unary_invocable<int (*)(int*, int*), int*>);
|
||||
static_assert(!std::indirectly_regular_unary_invocable<int (&)(int*, int*), int*>);
|
||||
static_assert(!std::indirectly_regular_unary_invocable<int (S::*)(int*), S*>);
|
||||
static_assert(!std::indirectly_regular_unary_invocable<int (S::*)(int*) const, S*>);
|
|
@ -0,0 +1,89 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
// UNSUPPORTED: gcc-10
|
||||
|
||||
// template<class F, class I>
|
||||
// concept indirectly_unary_invocable;
|
||||
|
||||
#include <iterator>
|
||||
#include <concepts>
|
||||
|
||||
#include "indirectly_readable.h"
|
||||
|
||||
using It = IndirectlyReadable<struct Token>;
|
||||
using R1 = T1<struct ReturnToken>;
|
||||
using R2 = T2<struct ReturnToken>;
|
||||
|
||||
template <class I>
|
||||
struct GoodInvocable {
|
||||
R1 operator()(std::iter_value_t<I>&) const;
|
||||
R2 operator()(std::iter_reference_t<I>) const;
|
||||
R2 operator()(std::iter_common_reference_t<I>) const;
|
||||
};
|
||||
|
||||
// Should work when all constraints are satisfied
|
||||
static_assert(std::indirectly_unary_invocable<GoodInvocable<It>, It>);
|
||||
|
||||
// Should fail when the iterator is not indirectly_readable
|
||||
struct NotIndirectlyReadable { };
|
||||
static_assert(!std::indirectly_unary_invocable<GoodInvocable<NotIndirectlyReadable>, NotIndirectlyReadable>);
|
||||
|
||||
// Should fail when the invocable is not copy constructible
|
||||
struct BadInvocable1 {
|
||||
BadInvocable1(BadInvocable1 const&) = delete;
|
||||
template <class T> R1 operator()(T const&) const;
|
||||
};
|
||||
static_assert(!std::indirectly_unary_invocable<BadInvocable1, It>);
|
||||
|
||||
// Should fail when the invocable can't be called with (iter_value_t&)
|
||||
struct BadInvocable2 {
|
||||
template <class T> R1 operator()(T const&) const;
|
||||
R1 operator()(std::iter_value_t<It>&) const = delete;
|
||||
};
|
||||
static_assert(!std::indirectly_unary_invocable<BadInvocable2, It>);
|
||||
|
||||
// Should fail when the invocable can't be called with (iter_reference_t)
|
||||
struct BadInvocable3 {
|
||||
template <class T> R1 operator()(T const&) const;
|
||||
R1 operator()(std::iter_reference_t<It>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirectly_unary_invocable<BadInvocable3, It>);
|
||||
|
||||
// Should fail when the invocable can't be called with (iter_common_reference_t)
|
||||
struct BadInvocable4 {
|
||||
template <class T> R1 operator()(T const&) const;
|
||||
R1 operator()(std::iter_common_reference_t<It>) const = delete;
|
||||
};
|
||||
static_assert(!std::indirectly_unary_invocable<BadInvocable4, It>);
|
||||
|
||||
// Should fail when the invocable doesn't have a common reference between its return types
|
||||
struct BadInvocable5 {
|
||||
R1 operator()(std::iter_value_t<It>&) const;
|
||||
struct Unrelated { };
|
||||
Unrelated operator()(std::iter_reference_t<It>) const;
|
||||
R1 operator()(std::iter_common_reference_t<It>) const;
|
||||
};
|
||||
static_assert(!std::indirectly_unary_invocable<BadInvocable5, It>);
|
||||
|
||||
// Various tests with callables
|
||||
struct S;
|
||||
static_assert(std::indirectly_unary_invocable<int (*)(int), int*>);
|
||||
static_assert(std::indirectly_unary_invocable<int (&)(int), int*>);
|
||||
static_assert(std::indirectly_unary_invocable<int S::*, S*>);
|
||||
static_assert(std::indirectly_unary_invocable<int (S::*)(), S*>);
|
||||
static_assert(std::indirectly_unary_invocable<int (S::*)() const, S*>);
|
||||
static_assert(std::indirectly_unary_invocable<void(*)(int), int*>);
|
||||
|
||||
static_assert(!std::indirectly_unary_invocable<int(int), int*>); // not move constructible
|
||||
static_assert(!std::indirectly_unary_invocable<int (*)(int*, int*), int*>);
|
||||
static_assert(!std::indirectly_unary_invocable<int (&)(int*, int*), int*>);
|
||||
static_assert(!std::indirectly_unary_invocable<int (S::*)(int*), S*>);
|
||||
static_assert(!std::indirectly_unary_invocable<int (S::*)(int*) const, S*>);
|
|
@ -0,0 +1,66 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
// UNSUPPORTED: gcc-10
|
||||
|
||||
// projected
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include <concepts>
|
||||
#include <functional>
|
||||
|
||||
#include "test_iterators.h"
|
||||
|
||||
using IntPtr = std::projected<int const*, std::identity>;
|
||||
static_assert(std::same_as<IntPtr::value_type, int>);
|
||||
static_assert(std::same_as<decltype(*std::declval<IntPtr>()), int const&>);
|
||||
static_assert(std::same_as<std::iter_difference_t<IntPtr>, std::ptrdiff_t>);
|
||||
|
||||
struct S { };
|
||||
|
||||
using Cpp17InputIterator = std::projected<cpp17_input_iterator<S*>, int S::*>;
|
||||
static_assert(std::same_as<Cpp17InputIterator::value_type, int>);
|
||||
static_assert(std::same_as<decltype(*std::declval<Cpp17InputIterator>()), int&>);
|
||||
static_assert(std::same_as<std::iter_difference_t<Cpp17InputIterator>, std::ptrdiff_t>);
|
||||
|
||||
using Cpp20InputIterator = std::projected<cpp20_input_iterator<S*>, int S::*>;
|
||||
static_assert(std::same_as<Cpp20InputIterator::value_type, int>);
|
||||
static_assert(std::same_as<decltype(*std::declval<Cpp20InputIterator>()), int&>);
|
||||
static_assert(std::same_as<std::iter_difference_t<Cpp20InputIterator>, std::ptrdiff_t>);
|
||||
|
||||
using ForwardIterator = std::projected<forward_iterator<S*>, int (S::*)()>;
|
||||
static_assert(std::same_as<ForwardIterator::value_type, int>);
|
||||
static_assert(std::same_as<decltype(*std::declval<ForwardIterator>()), int>);
|
||||
static_assert(std::same_as<std::iter_difference_t<ForwardIterator>, std::ptrdiff_t>);
|
||||
|
||||
using BidirectionalIterator = std::projected<bidirectional_iterator<S*>, S* (S::*)() const>;
|
||||
static_assert(std::same_as<BidirectionalIterator::value_type, S*>);
|
||||
static_assert(std::same_as<decltype(*std::declval<BidirectionalIterator>()), S*>);
|
||||
static_assert(std::same_as<std::iter_difference_t<BidirectionalIterator>, std::ptrdiff_t>);
|
||||
|
||||
using RandomAccessIterator = std::projected<random_access_iterator<S*>, S && (S::*)()>;
|
||||
static_assert(std::same_as<RandomAccessIterator::value_type, S>);
|
||||
static_assert(std::same_as<decltype(*std::declval<RandomAccessIterator>()), S&&>);
|
||||
static_assert(std::same_as<std::iter_difference_t<RandomAccessIterator>, std::ptrdiff_t>);
|
||||
|
||||
using ContiguousIterator = std::projected<contiguous_iterator<S*>, S& (S::*)() const>;
|
||||
static_assert(std::same_as<ContiguousIterator::value_type, S>);
|
||||
static_assert(std::same_as<decltype(*std::declval<ContiguousIterator>()), S&>);
|
||||
static_assert(std::same_as<std::iter_difference_t<ContiguousIterator>, std::ptrdiff_t>);
|
||||
|
||||
template <class I, class F>
|
||||
constexpr bool projectable = requires {
|
||||
typename std::projected<I, F>;
|
||||
};
|
||||
|
||||
static_assert(!projectable<int, void (*)(int)>); // int isn't indirectly_readable
|
||||
static_assert(!projectable<S, void (*)(int)>); // S isn't weakly_incrementable
|
||||
static_assert(!projectable<int*, void(int)>); // void(int) doesn't satisfy indirectly_regular_unary_invcable
|
|
@ -0,0 +1,60 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
// UNSUPPORTED: gcc-10
|
||||
|
||||
// iter_common_reference_t
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include <concepts>
|
||||
|
||||
struct X { };
|
||||
|
||||
// value_type and dereferencing are the same
|
||||
struct T1 {
|
||||
using value_type = X;
|
||||
X operator*() const;
|
||||
};
|
||||
static_assert(std::same_as<std::iter_common_reference_t<T1>, X>);
|
||||
|
||||
// value_type and dereferencing are the same (modulo qualifiers)
|
||||
struct T2 {
|
||||
using value_type = X;
|
||||
X& operator*() const;
|
||||
};
|
||||
static_assert(std::same_as<std::iter_common_reference_t<T2>, X&>);
|
||||
|
||||
// There's a custom common reference between value_type and the type of dereferencing
|
||||
struct A { };
|
||||
struct B { };
|
||||
struct Common { Common(A); Common(B); };
|
||||
template <template <class> class TQual, template <class> class QQual>
|
||||
struct std::basic_common_reference<A, B, TQual, QQual> {
|
||||
using type = Common;
|
||||
};
|
||||
template <template <class> class TQual, template <class> class QQual>
|
||||
struct std::basic_common_reference<B, A, TQual, QQual>
|
||||
: std::basic_common_reference<A, B, TQual, QQual>
|
||||
{ };
|
||||
|
||||
struct T3 {
|
||||
using value_type = A;
|
||||
B&& operator*() const;
|
||||
};
|
||||
static_assert(std::same_as<std::iter_common_reference_t<T3>, Common>);
|
||||
|
||||
// Make sure we're SFINAE-friendly
|
||||
template <class T>
|
||||
constexpr bool has_common_reference = requires {
|
||||
typename std::iter_common_reference_t<T>;
|
||||
};
|
||||
struct NotIndirectlyReadable { };
|
||||
static_assert(!has_common_reference<NotIndirectlyReadable>);
|
|
@ -0,0 +1,38 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LIBCXX_TEST_SUPPORT_INDIRECTLY_READABLE_H
|
||||
#define LIBCXX_TEST_SUPPORT_INDIRECTLY_READABLE_H
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
template <class Token>
|
||||
struct Common { };
|
||||
|
||||
template <class Token>
|
||||
struct T1 : Common<Token> { };
|
||||
|
||||
template <class Token>
|
||||
struct T2 : Common<Token> { };
|
||||
|
||||
template <template <class> class T1Qual, template <class> class T2Qual, class Token>
|
||||
struct std::basic_common_reference<T1<Token>, T2<Token>, T1Qual, T2Qual> {
|
||||
using type = Common<Token>;
|
||||
};
|
||||
template <template <class> class T2Qual, template <class> class T1Qual, class Token>
|
||||
struct std::basic_common_reference<T2<Token>, T1<Token>, T2Qual, T1Qual>
|
||||
: std::basic_common_reference<T1<Token>, T2<Token>, T1Qual, T2Qual>
|
||||
{ };
|
||||
|
||||
template <class Token>
|
||||
struct IndirectlyReadable {
|
||||
using value_type = T1<Token>;
|
||||
T2<Token>& operator*() const;
|
||||
};
|
||||
|
||||
#endif // LIBCXX_TEST_SUPPORT_INDIRECTLY_READABLE_H
|
Loading…
Reference in New Issue