//===----------------------------------------------------------------------===//
//
// 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, c++20
// test forward_like
#include <cassert>
#include <type_traits>
#include <utility>
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(std::is_same_v<decltype(std::forward_like<T>(U{})), U&&>);
static_assert(std::is_same_v<decltype(std::forward_like<T>(CU{})), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<T>(u)), U&&>);
static_assert(std::is_same_v<decltype(std::forward_like<T>(cu)), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<T>(std::move(u))), U&&>);
static_assert(std::is_same_v<decltype(std::forward_like<T>(std::move(cu))), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT>(U{})), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT>(CU{})), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT>(u)), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT>(cu)), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT>(std::move(u))), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT>(std::move(cu))), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<T&>(U{})), U&>);
static_assert(std::is_same_v<decltype(std::forward_like<T&>(CU{})), CU&>);
static_assert(std::is_same_v<decltype(std::forward_like<T&>(u)), U&>);
static_assert(std::is_same_v<decltype(std::forward_like<T&>(cu)), CU&>);
static_assert(std::is_same_v<decltype(std::forward_like<T&>(std::move(u))), U&>);
static_assert(std::is_same_v<decltype(std::forward_like<T&>(std::move(cu))), CU&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT&>(U{})), CU&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT&>(CU{})), CU&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT&>(u)), CU&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT&>(cu)), CU&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT&>(std::move(u))), CU&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT&>(std::move(cu))), CU&>);
static_assert(std::is_same_v<decltype(std::forward_like<T&&>(U{})), U&&>);
static_assert(std::is_same_v<decltype(std::forward_like<T&&>(CU{})), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<T&&>(u)), U&&>);
static_assert(std::is_same_v<decltype(std::forward_like<T&&>(cu)), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<T&&>(std::move(u))), U&&>);
static_assert(std::is_same_v<decltype(std::forward_like<T&&>(std::move(cu))), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT&&>(U{})), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT&&>(CU{})), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT&&>(u)), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT&&>(cu)), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT&&>(std::move(u))), CU&&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT&&>(std::move(cu))), CU&&>);
static_assert(noexcept(std::forward_like<T>(u)));
static_assert(std::is_same_v<decltype(std::forward_like<U&>(u)), U&>);
static_assert(std::is_same_v<decltype(std::forward_like<CU&>(cu)), CU&>);
static_assert(std::is_same_v<decltype(std::forward_like<U&&>(std::move(u))), U&&>);
static_assert(std::is_same_v<decltype(std::forward_like<CU&&>(std::move(cu))), CU&&>);
struct NoCtorCopyMove {
NoCtorCopyMove() = delete;
NoCtorCopyMove(const NoCtorCopyMove&) = delete;
NoCtorCopyMove(NoCtorCopyMove&&) = delete;
};
static_assert(std::is_same_v<decltype(std::forward_like<CT&&>(std::declval<NoCtorCopyMove>())), const NoCtorCopyMove&&>);
static_assert(std::is_same_v<decltype(std::forward_like<CT&>(std::declval<NoCtorCopyMove>())), const NoCtorCopyMove&>);
static_assert(std::is_same_v<decltype(std::forward_like<T&&>(std::declval<NoCtorCopyMove>())), NoCtorCopyMove&&>);
static_assert(std::is_same_v<decltype(std::forward_like<T&>(std::declval<NoCtorCopyMove>())), NoCtorCopyMove&>);
static_assert(noexcept(std::forward_like<T>(std::declval<NoCtorCopyMove>())));
constexpr bool test() {
{
int val = 1729;
auto&& result = std::forward_like<const double&>(val);
static_assert(std::is_same_v<decltype(result), const int&>);
assert(&result == &val);
}
{
int val = 1729;
auto&& result = std::forward_like<double&>(val);
static_assert(std::is_same_v<decltype(result), int&>);
assert(&result == &val);
}
{
int val = 1729;
auto&& result = std::forward_like<const double&&>(val);
static_assert(std::is_same_v<decltype(result), const int&&>);
assert(&result == &val);
}
{
int val = 1729;
auto&& result = std::forward_like<double&&>(val);
static_assert(std::is_same_v<decltype(result), int&&>);
assert(&result == &val);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}