зеркало из https://github.com/microsoft/STL.git
Implement P2445R1 `forward_like()` (#2974)
Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
This commit is contained in:
Родитель
097e59ba9a
Коммит
577269c56a
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче