Implement P2445R1 `forward_like()` (#2974)

Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
This commit is contained in:
A. Jiang 2022-08-06 07:40:30 +08:00 коммит произвёл GitHub
Родитель 097e59ba9a
Коммит 577269c56a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 130 добавлений и 8 удалений

Просмотреть файл

@ -32,14 +32,6 @@ struct random_access_iterator_tag : bidirectional_iterator_tag {};
#ifdef __cpp_lib_concepts
struct contiguous_iterator_tag : random_access_iterator_tag {};
template <class _Ty>
using _With_reference = _Ty&;
template <class _Ty>
concept _Can_reference = requires {
typename _With_reference<_Ty>;
};
template <class _Ty>
concept _Dereferenceable = requires(_Ty& __t) {
{ *__t } -> _Can_reference;

Просмотреть файл

@ -788,6 +788,22 @@ _NODISCARD constexpr bool in_range(const _Ty _Value) noexcept {
return true;
}
#ifdef __cpp_lib_concepts
template <class _Ty>
using _With_reference = _Ty&;
template <class _Ty>
concept _Can_reference = requires {
typename _With_reference<_Ty>;
};
#else // __cpp_lib_concepts
template <class _Ty, class = void>
inline constexpr bool _Can_reference = false;
template <class _Ty>
inline constexpr bool _Can_reference<_Ty, void_t<_Ty&>> = true;
#endif // __cpp_lib_concepts
#endif // _HAS_CXX20
#if _HAS_CXX23
@ -802,6 +818,27 @@ _NODISCARD constexpr underlying_type_t<_Ty> to_underlying(_Ty _Value) noexcept {
_CSTD abort(); // likely to be called in debug mode, but can't be relied upon - already entered the UB territory
#endif // _DEBUG
}
template <class _Ty, class _Uty>
_NODISCARD constexpr auto&& forward_like(_Uty&& _Ux) noexcept {
static_assert(_Can_reference<_Ty>, "std::forward_like's first template argument must be a referenceable type.");
using _UnrefT = remove_reference_t<_Ty>;
using _UnrefU = remove_reference_t<_Uty>;
if constexpr (is_const_v<_UnrefT>) {
if constexpr (is_lvalue_reference_v<_Ty>) {
return static_cast<const _UnrefU&>(_Ux);
} else {
return static_cast<const _UnrefU&&>(_Ux);
}
} else {
if constexpr (is_lvalue_reference_v<_Ty>) {
return static_cast<_UnrefU&>(_Ux);
} else {
return static_cast<_UnrefU&&>(_Ux);
}
}
}
#endif // _HAS_CXX23
#if _HAS_TR1_NAMESPACE

Просмотреть файл

@ -326,6 +326,7 @@
// P2441R2 views::join_with
// P2442R1 Windowing Range Adaptors: views::chunk, views::slide
// P2443R1 views::chunk_by
// P2445R1 forward_like()
// P2499R0 string_view Range Constructor Should Be explicit
// P2549R0 unexpected<E>::error()
@ -1496,6 +1497,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect
#define __cpp_lib_expected 202202L
#endif // __cpp_lib_concepts
#define __cpp_lib_forward_like 202207L
#define __cpp_lib_invoke_r 202106L
#define __cpp_lib_is_scoped_enum 202011L
#define __cpp_lib_move_only_function 202110L

Просмотреть файл

@ -502,6 +502,7 @@ tests\P2442R1_views_chunk_death
tests\P2442R1_views_slide
tests\P2443R1_views_chunk_by
tests\P2443R1_views_chunk_by_death
tests\P2445R1_forward_like
tests\P2517R1_apply_conditional_noexcept
tests\VSO_0000000_allocator_propagation
tests\VSO_0000000_any_calling_conventions

Просмотреть файл

@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
RUNALL_INCLUDE ..\usual_latest_matrix.lst

Просмотреть файл

@ -0,0 +1,72 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <cassert>
#include <type_traits>
#include <utility>
using namespace std;
struct U {}; // class type so const-qualification is not stripped from a prvalue
using CU = const U;
using T = int;
using CT = const T;
U u{};
const U& cu = u;
static_assert(is_same_v<decltype(forward_like<T>(U{})), U&&>);
static_assert(is_same_v<decltype(forward_like<T>(CU{})), CU&&>);
static_assert(is_same_v<decltype(forward_like<T>(u)), U&&>);
static_assert(is_same_v<decltype(forward_like<T>(cu)), CU&&>);
static_assert(is_same_v<decltype(forward_like<T>(move(u))), U&&>);
static_assert(is_same_v<decltype(forward_like<T>(move(cu))), CU&&>);
static_assert(is_same_v<decltype(forward_like<CT>(U{})), CU&&>);
static_assert(is_same_v<decltype(forward_like<CT>(CU{})), CU&&>);
static_assert(is_same_v<decltype(forward_like<CT>(u)), CU&&>);
static_assert(is_same_v<decltype(forward_like<CT>(cu)), CU&&>);
static_assert(is_same_v<decltype(forward_like<CT>(move(u))), CU&&>);
static_assert(is_same_v<decltype(forward_like<CT>(move(cu))), CU&&>);
static_assert(is_same_v<decltype(forward_like<T&>(U{})), U&>);
static_assert(is_same_v<decltype(forward_like<T&>(CU{})), CU&>);
static_assert(is_same_v<decltype(forward_like<T&>(u)), U&>);
static_assert(is_same_v<decltype(forward_like<T&>(cu)), CU&>);
static_assert(is_same_v<decltype(forward_like<T&>(move(u))), U&>);
static_assert(is_same_v<decltype(forward_like<T&>(move(cu))), CU&>);
static_assert(is_same_v<decltype(forward_like<CT&>(U{})), CU&>);
static_assert(is_same_v<decltype(forward_like<CT&>(CU{})), CU&>);
static_assert(is_same_v<decltype(forward_like<CT&>(u)), CU&>);
static_assert(is_same_v<decltype(forward_like<CT&>(cu)), CU&>);
static_assert(is_same_v<decltype(forward_like<CT&>(move(u))), CU&>);
static_assert(is_same_v<decltype(forward_like<CT&>(move(cu))), CU&>);
static_assert(is_same_v<decltype(forward_like<T&&>(U{})), U&&>);
static_assert(is_same_v<decltype(forward_like<T&&>(CU{})), CU&&>);
static_assert(is_same_v<decltype(forward_like<T&&>(u)), U&&>);
static_assert(is_same_v<decltype(forward_like<T&&>(cu)), CU&&>);
static_assert(is_same_v<decltype(forward_like<T&&>(move(u))), U&&>);
static_assert(is_same_v<decltype(forward_like<T&&>(move(cu))), CU&&>);
static_assert(is_same_v<decltype(forward_like<CT&&>(U{})), CU&&>);
static_assert(is_same_v<decltype(forward_like<CT&&>(CU{})), CU&&>);
static_assert(is_same_v<decltype(forward_like<CT&&>(u)), CU&&>);
static_assert(is_same_v<decltype(forward_like<CT&&>(cu)), CU&&>);
static_assert(is_same_v<decltype(forward_like<CT&&>(move(u))), CU&&>);
static_assert(is_same_v<decltype(forward_like<CT&&>(move(cu))), CU&&>);
static_assert(noexcept(forward_like<T>(u)));
constexpr bool test() {
int val = 1729;
auto&& result = forward_like<const double&>(val);
static_assert(is_same_v<decltype(result), const int&>);
assert(&result == &val);
return true;
}
static_assert(test());
int main() {} // COMPILE-ONLY

Просмотреть файл

@ -814,6 +814,20 @@ STATIC_ASSERT(__cpp_lib_format == 202110L);
#endif
#endif
#if _HAS_CXX23
#ifndef __cpp_lib_forward_like
#error __cpp_lib_forward_like is not defined
#elif __cpp_lib_forward_like != 202207L
#error __cpp_lib_forward_like is not 202207L
#else
STATIC_ASSERT(__cpp_lib_forward_like == 202207L);
#endif
#else
#ifdef __cpp_lib_forward_like
#error __cpp_lib_forward_like is defined
#endif
#endif
#if _HAS_CXX17
#ifndef __cpp_lib_gcd_lcm
#error __cpp_lib_gcd_lcm is not defined