Refactor hasCompareThreeWay check

Use structs derived from std::false_type and std::true_type instead
of boolean constants. This allows us to make use of std::conjunction_v
and std::disjunciton_v in the conditions, thus making use of
short-circuit evaluation and saving unnecessary template
instantiations.

Still keep the constexpr bool *_v constant for the cases when we need
a signle check only.

Amends 678e9f614bc5a05d2ff16cf916397998e7cdfca1.

Pick-to: 6.9 6.8
Change-Id: If2ab48ef910e97f241f5922d4108a271bc532f3a
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Ivan Solovev 2024-11-21 13:10:27 +01:00
parent b6f3695a80
commit 8784ea16a6
2 changed files with 20 additions and 14 deletions

View File

@ -647,14 +647,15 @@ auto qCompareThreeWay(const LeftType &lhs, const RightType &rhs);
template <typename LT, typename RT, template <typename LT, typename RT,
std::enable_if_t< std::enable_if_t<
QtOrderingPrivate::CompareThreeWayTester::hasCompareThreeWay<LT, RT> std::disjunction_v<
|| QtOrderingPrivate::CompareThreeWayTester::hasCompareThreeWay<RT, LT>, QtOrderingPrivate::CompareThreeWayTester::HasCompareThreeWay<LT, RT>,
QtOrderingPrivate::CompareThreeWayTester::HasCompareThreeWay<RT, LT>>,
bool> = true> bool> = true>
auto qCompareThreeWay(const LT &lhs, const RT &rhs) auto qCompareThreeWay(const LT &lhs, const RT &rhs)
noexcept(QtOrderingPrivate::CompareThreeWayTester::compareThreeWayNoexcept<LT, RT>()) noexcept(QtOrderingPrivate::CompareThreeWayTester::compareThreeWayNoexcept<LT, RT>())
{ {
using Qt::compareThreeWay; using Qt::compareThreeWay;
if constexpr (QtOrderingPrivate::CompareThreeWayTester::hasCompareThreeWay<LT, RT>) { if constexpr (QtOrderingPrivate::CompareThreeWayTester::hasCompareThreeWay_v<LT, RT>) {
return compareThreeWay(lhs, rhs); return compareThreeWay(lhs, rhs);
} else { } else {
const auto retval = compareThreeWay(rhs, lhs); const auto retval = compareThreeWay(rhs, lhs);

View File

@ -1201,19 +1201,22 @@ using WrappedType = std::conditional_t<std::is_pointer_v<T>, Qt::totally_ordered
// Check if compareThreeWay is implemented for the (LT, RT) argument // Check if compareThreeWay is implemented for the (LT, RT) argument
// pair. // pair.
template <typename LT, typename RT, typename = void> template <typename LT, typename RT, typename = void>
constexpr inline bool hasCompareThreeWay = false; struct HasCompareThreeWay : std::false_type {};
template <typename LT, typename RT> template <typename LT, typename RT>
constexpr inline bool hasCompareThreeWay< struct HasCompareThreeWay<
LT, RT, std::void_t<decltype(compareThreeWay(std::declval<LT>(), std::declval<RT>()))> LT, RT, std::void_t<decltype(compareThreeWay(std::declval<LT>(), std::declval<RT>()))>
> = true; > : std::true_type {};
template <typename LT, typename RT> template <typename LT, typename RT>
constexpr inline bool hasCompareThreeWay< struct HasCompareThreeWay<
LT*, RT*, LT*, RT*,
std::void_t<decltype(compareThreeWay(std::declval<WrappedType<LT>>(), std::void_t<decltype(compareThreeWay(std::declval<WrappedType<LT>>(),
std::declval<WrappedType<RT>>()))> std::declval<WrappedType<RT>>()))>
> = true; > : std::true_type {};
template <typename LT, typename RT>
constexpr inline bool hasCompareThreeWay_v = HasCompareThreeWay<LT, RT>::value;
// Check if the operation is noexcept. We have two different overloads, // Check if the operation is noexcept. We have two different overloads,
// depending on the available compareThreeWay() implementation. // depending on the available compareThreeWay() implementation.
@ -1221,12 +1224,13 @@ constexpr inline bool hasCompareThreeWay<
// context. // context.
template <typename LT, typename RT, template <typename LT, typename RT,
std::enable_if_t<hasCompareThreeWay<LT, RT>, bool> = true> std::enable_if_t<hasCompareThreeWay_v<LT, RT>, bool> = true>
constexpr bool compareThreeWayNoexcept() noexcept constexpr bool compareThreeWayNoexcept() noexcept
{ return noexcept(compareThreeWay(std::declval<LT>(), std::declval<RT>())); } { return noexcept(compareThreeWay(std::declval<LT>(), std::declval<RT>())); }
template <typename LT, typename RT, template <typename LT, typename RT,
std::enable_if_t<!hasCompareThreeWay<LT, RT> && hasCompareThreeWay<RT, LT>, std::enable_if_t<std::conjunction_v<std::negation<HasCompareThreeWay<LT, RT>>,
HasCompareThreeWay<RT, LT>>,
bool> = true> bool> = true>
constexpr bool compareThreeWayNoexcept() noexcept constexpr bool compareThreeWayNoexcept() noexcept
{ return noexcept(compareThreeWay(std::declval<RT>(), std::declval<LT>())); } { return noexcept(compareThreeWay(std::declval<RT>(), std::declval<LT>())); }
@ -1319,7 +1323,7 @@ auto lexicographicalCompareThreeWay(InputIt1 first1, InputIt1 last1,
namespace Test = QtOrderingPrivate::CompareThreeWayTester; namespace Test = QtOrderingPrivate::CompareThreeWayTester;
// Need this because the user might provide only // Need this because the user might provide only
// compareThreeWay(LT, RT), but not the reversed version. // compareThreeWay(LT, RT), but not the reversed version.
if constexpr (Test::hasCompareThreeWay<WrapLT, WrapRT>) if constexpr (Test::hasCompareThreeWay_v<WrapLT, WrapRT>)
return compareThreeWay(WrapLT(lhs), WrapRT(rhs)); return compareThreeWay(WrapLT(lhs), WrapRT(rhs));
else else
return QtOrderingPrivate::reversed(compareThreeWay(WrapRT(rhs), WrapLT(lhs))); return QtOrderingPrivate::reversed(compareThreeWay(WrapRT(rhs), WrapLT(lhs)));
@ -1333,9 +1337,10 @@ namespace Qt {
template <typename T, typename U> template <typename T, typename U>
using if_has_qt_compare_three_way = using if_has_qt_compare_three_way =
std::enable_if_t<QtOrderingPrivate::CompareThreeWayTester::hasCompareThreeWay<T, U> std::enable_if_t<
|| QtOrderingPrivate::CompareThreeWayTester::hasCompareThreeWay<U, T>, std::disjunction_v<QtOrderingPrivate::CompareThreeWayTester::HasCompareThreeWay<T, U>,
bool>; QtOrderingPrivate::CompareThreeWayTester::HasCompareThreeWay<U, T>>,
bool>;
} // namespace Qt } // namespace Qt