mirror of
https://github.com/ETLCPP/etl.git
synced 2026-06-16 00:46:03 +08:00
Added etl::forward_like
This commit is contained in:
parent
5977555f3b
commit
73c96a4c6c
@ -68,6 +68,55 @@ namespace etl
|
||||
ETL_STATIC_ASSERT(!etl::is_lvalue_reference<T>::value, "Invalid rvalue to lvalue conversion");
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
/// See std::forward_like https://en.cppreference.com/w/cpp/utility/forward_like
|
||||
/// Returns a reference to x which has similar properties to T&&.
|
||||
///\return
|
||||
/// If etl::remove_reference_t<T> is const then returns a const reference if U is an lvalue, otherwise a const rvalue reference.
|
||||
/// If etl::remove_reference_t<T> is not const then returns a reference if U is an lvalue, otherwise an rvalue reference.
|
||||
//******************************************************************************
|
||||
template <typename T, typename U>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
auto&& forward_like(U&& u) ETL_NOEXCEPT
|
||||
{
|
||||
using TType = etl::remove_reference_t<T>;
|
||||
using UType = etl::remove_reference_t<U>;
|
||||
|
||||
if ETL_IF_CONSTEXPR (etl::is_const<TType>::value)
|
||||
{
|
||||
// For const TType
|
||||
if ETL_IF_CONSTEXPR (etl::is_lvalue_reference<T>::value)
|
||||
{
|
||||
// const lvalue
|
||||
return static_cast<const UType&>(u);
|
||||
}
|
||||
else
|
||||
{
|
||||
// const rvalue
|
||||
return static_cast<const UType&&>(u);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// For non-const TType
|
||||
if ETL_IF_CONSTEXPR (etl::is_lvalue_reference<T>::value)
|
||||
{
|
||||
// lvalue
|
||||
return static_cast<UType&>(u);
|
||||
}
|
||||
else
|
||||
{
|
||||
// rvalue
|
||||
return static_cast<UType&&>(u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Defines the type that forward_like would cast to.
|
||||
template <typename T, typename U>
|
||||
using forward_like_t = decltype(etl::forward_like<T>(etl::declval<U&>()));
|
||||
#endif
|
||||
|
||||
// We can't have std::swap and etl::swap templates coexisting in the unit tests
|
||||
@ -612,4 +661,3 @@ namespace etl
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -432,5 +432,238 @@ namespace
|
||||
|
||||
CHECK_EQUAL(2, pf(1));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
struct SF
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
//*********************************
|
||||
enum class forward_call_type
|
||||
{
|
||||
LValue,
|
||||
ConstLValue,
|
||||
RValue,
|
||||
ConstRValue
|
||||
};
|
||||
|
||||
//*********************************
|
||||
std::ostream& operator << (std::ostream& os, forward_call_type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case forward_call_type::LValue:
|
||||
{
|
||||
os << "LValue";
|
||||
break;
|
||||
}
|
||||
|
||||
case forward_call_type::ConstLValue:
|
||||
{
|
||||
os << "ConstLValue";
|
||||
break;
|
||||
}
|
||||
|
||||
case forward_call_type::RValue:
|
||||
{
|
||||
os << "RValue";
|
||||
break;
|
||||
}
|
||||
|
||||
case forward_call_type::ConstRValue:
|
||||
{
|
||||
os << "ConstRValue";
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
os << "Unknown type";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
//*********************************
|
||||
forward_call_type function_f(SF&)
|
||||
{
|
||||
return forward_call_type::LValue;
|
||||
}
|
||||
|
||||
//*********************************
|
||||
forward_call_type function_f(const SF&)
|
||||
{
|
||||
return forward_call_type::ConstLValue;
|
||||
}
|
||||
|
||||
//*********************************
|
||||
forward_call_type function_f(SF&&)
|
||||
{
|
||||
return forward_call_type::RValue;
|
||||
}
|
||||
|
||||
//*********************************
|
||||
forward_call_type function_f(const SF&&)
|
||||
{
|
||||
return forward_call_type::ConstRValue;
|
||||
}
|
||||
|
||||
//*********************************
|
||||
template <typename T>
|
||||
forward_call_type template_function_f(T&& t)
|
||||
{
|
||||
return function_f(etl::forward<T>(t));
|
||||
}
|
||||
|
||||
//*********************************
|
||||
TEST(test_forward)
|
||||
{
|
||||
SF s1;
|
||||
const SF s2;
|
||||
|
||||
CHECK_EQUAL(forward_call_type::LValue, template_function_f(s1));
|
||||
CHECK_EQUAL(forward_call_type::RValue, template_function_f(etl::move(s1)));
|
||||
CHECK_EQUAL(forward_call_type::ConstLValue, template_function_f(s2));
|
||||
CHECK_EQUAL(forward_call_type::ConstRValue, template_function_f(etl::move(s2)));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
struct TFL
|
||||
{
|
||||
};
|
||||
|
||||
struct UFL
|
||||
{
|
||||
};
|
||||
|
||||
enum class forward_like_call_type
|
||||
{
|
||||
LValue,
|
||||
ConstLValue,
|
||||
RValue,
|
||||
ConstRValue
|
||||
};
|
||||
|
||||
//*********************************
|
||||
std::ostream& operator << (std::ostream& os, forward_like_call_type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case forward_like_call_type::LValue:
|
||||
{
|
||||
os << "LValue";
|
||||
break;
|
||||
}
|
||||
|
||||
case forward_like_call_type::ConstLValue:
|
||||
{
|
||||
os << "ConstLValue";
|
||||
break;
|
||||
}
|
||||
|
||||
case forward_like_call_type::RValue:
|
||||
{
|
||||
os << "RValue";
|
||||
break;
|
||||
}
|
||||
|
||||
case forward_like_call_type::ConstRValue:
|
||||
{
|
||||
os << "ConstRValue";
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
os << "Unknown type";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
//*********************************
|
||||
forward_like_call_type function_fl(UFL&)
|
||||
{
|
||||
return forward_like_call_type::LValue;
|
||||
}
|
||||
|
||||
//*********************************
|
||||
forward_like_call_type function_fl(const UFL&)
|
||||
{
|
||||
return forward_like_call_type::ConstLValue;
|
||||
}
|
||||
|
||||
//*********************************
|
||||
forward_like_call_type function_fl(UFL&&)
|
||||
{
|
||||
return forward_like_call_type::RValue;
|
||||
}
|
||||
|
||||
//*********************************
|
||||
forward_like_call_type function_fl(const UFL&&)
|
||||
{
|
||||
return forward_like_call_type::ConstRValue;
|
||||
}
|
||||
|
||||
//*********************************
|
||||
template <typename T, typename U>
|
||||
forward_like_call_type template_function_fl(U&& u)
|
||||
{
|
||||
return function_fl(etl::forward_like<T>(u));
|
||||
}
|
||||
|
||||
//*********************************
|
||||
TEST(test_forward_like)
|
||||
{
|
||||
UFL u1;
|
||||
const UFL u2;
|
||||
UFL& u3 = u1;
|
||||
const UFL& u4 = u2;
|
||||
|
||||
CHECK_EQUAL(forward_like_call_type::LValue, template_function_fl<TFL&>(u1));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstLValue, template_function_fl<const TFL&>(u1));
|
||||
CHECK_EQUAL(forward_like_call_type::RValue, template_function_fl<TFL&&>(u1));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl<const TFL&&>(u1));
|
||||
|
||||
CHECK_EQUAL(forward_like_call_type::LValue, template_function_fl<TFL&>(etl::move(u1)));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstLValue, template_function_fl<const TFL&>(etl::move(u1)));
|
||||
CHECK_EQUAL(forward_like_call_type::RValue, template_function_fl<TFL&&>(etl::move(u1)));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl<const TFL&&>(etl::move(u1)));
|
||||
|
||||
CHECK_EQUAL(forward_like_call_type::ConstLValue, template_function_fl<TFL&>(u2));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstLValue, template_function_fl<const TFL&>(u2));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl<TFL&&>(u2));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl<const TFL&&>(u2));
|
||||
|
||||
CHECK_EQUAL(forward_like_call_type::ConstLValue, template_function_fl<TFL&>(etl::move(u2)));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstLValue, template_function_fl<const TFL&>(etl::move(u2)));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl<TFL&&>(etl::move(u2)));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl<const TFL&&>(etl::move(u2)));
|
||||
|
||||
CHECK_EQUAL(forward_like_call_type::LValue, template_function_fl<TFL&>(u3));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstLValue, template_function_fl<const TFL&>(u3));
|
||||
CHECK_EQUAL(forward_like_call_type::RValue, template_function_fl<TFL&&>(u3));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl<const TFL&&>(u3));
|
||||
|
||||
CHECK_EQUAL(forward_like_call_type::LValue, template_function_fl<TFL&>(etl::move(u3)));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstLValue, template_function_fl<const TFL&>(etl::move(u3)));
|
||||
CHECK_EQUAL(forward_like_call_type::RValue, template_function_fl<TFL&&>(etl::move(u3)));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl<const TFL&&>(etl::move(u3)));
|
||||
|
||||
CHECK_EQUAL(forward_like_call_type::ConstLValue, template_function_fl<TFL&>(u4));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstLValue, template_function_fl<const TFL&>(u4));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl<TFL&&>(u4));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl<const TFL&&>(u4));
|
||||
|
||||
CHECK_EQUAL(forward_like_call_type::ConstLValue, template_function_fl<TFL&>(etl::move(u4)));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstLValue, template_function_fl<const TFL&>(etl::move(u4)));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl<TFL&&>(etl::move(u4)));
|
||||
CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl<const TFL&&>(etl::move(u4)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user