Short live q23::forward_like!

Following https://eel.is/c++draft/forward#lib:forward_like
step-by-step.

Temporarily add a q23utility.cpp to contain the static_assert()
tests. There's no point in establishing a tst_q23utility just to run
six static assertions. Should remove the .cpp again once an in-tree
user exercises the function with the same coverage.

Task-number: QTBUG-111598
Change-Id: Icb18eae089d65ca4e555921dbb71e74a7e255645
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Marc Mutz 2023-03-03 07:04:21 +01:00
parent 4bc0f4fbec
commit 28f56f29bb
3 changed files with 102 additions and 0 deletions

View File

@ -104,6 +104,8 @@ qt_internal_add_module(Core
global/q20memory.h
global/q20type_traits.h
global/q23functional.h
global/q23utility.cpp # remove once we have a user that tests this
global/q23utility.h
global/qxpfunctional.h
global/qxptype_traits.h
ipc/qsharedmemory.cpp ipc/qsharedmemory.h ipc/qsharedmemory_p.h

View File

@ -0,0 +1,25 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/q23utility.h>
QT_BEGIN_NAMESPACE
#define CHECK2(cvref_in, cvref_out) \
static_assert(std::is_same_v< \
decltype(q23::forward_like<int cvref_in >(std::declval<long&>())), \
long cvref_out \
>, "oops: cvref '" #cvref_in "' doesn't work") \
/* end */
#define CHECK(cvref) CHECK2(cvref, cvref)
CHECK2(/**/, &&);
CHECK(&);
CHECK(&&);
CHECK2(const, const &&);
CHECK(const &);
CHECK(const &&);
// volatile is not supported
#undef CHECK
#undef CHECK2
QT_END_NAMESPACE

View File

@ -0,0 +1,75 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef Q23UTILITY_H
#define Q23UTILITY_H
#include <QtCore/qtconfigmacros.h>
#include <utility>
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. Types and functions defined in this
// file can reliably be replaced by their std counterparts, once available.
// You may use these definitions in your own code, but be aware that we
// will remove them once Qt depends on the C++ version that supports
// them in namespace std. There will be NO deprecation warning, the
// definitions will JUST go away.
//
// If you can't agree to these terms, don't use these definitions!
//
// We mean it.
//
QT_BEGIN_NAMESPACE
namespace q23 {
// like std::forward_like
#ifdef __cpp_lib_forward_like
using std::forward_like;
#else
namespace _detail {
// [forward]/6.1 COPY_CONST
template <typename A, typename B>
using copy_const_t = std::conditional_t<
std::is_const_v<A>, const B,
/* else */ B
>;
// [forward]/6.2 OVERRIDE_REF
template <typename A, typename B>
using override_ref_t = std::conditional_t<
std::is_rvalue_reference_v<A>, std::remove_reference_t<B>&&,
/* else */ B&
>;
// [forward]/6.3 "V"
template <typename T, typename U>
using forward_like_ret_t = override_ref_t<
T&&,
copy_const_t<
std::remove_reference_t<T>,
std::remove_reference_t<U>
>
>;
} // namespace detail
// http://eel.is/c++draft/forward#lib:forward_like
template <class T, class U>
[[nodiscard]] constexpr auto forward_like(U &&x) noexcept
-> _detail::forward_like_ret_t<T, U>
{
using V = _detail::forward_like_ret_t<T, U>;
return static_cast<V>(x);
}
#endif // __cpp_lib_forward_like
} // namespace q23
QT_END_NAMESPACE
#endif /* Q23UTILITY_H */