Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorMartin Hořeňovský2026-09-04 20:54:35 +0200
committerMartin Hořeňovský2026-09-04 20:54:43 +0200
commit897d8043eb192d0fc361c6339ce13e1cabe481c4 (patch)
tree5f413a5429e7ffe953b4b30fc2e2affcc4c73bb7 /src
parentde1330d036168492a04b649a1fa0593faece6f74 (diff)
downloadcatch3-897d8043eb192d0fc361c6339ce13e1cabe481c4.tar.gz
Reduce number of instantiations of is_foo_comparable trait
This provides minor compile-time optimization.
Diffstat (limited to 'src')
-rw-r--r--src/catch2/internal/catch_compare_traits.hpp31
1 files changed, 25 insertions, 6 deletions
diff --git a/src/catch2/internal/catch_compare_traits.hpp b/src/catch2/internal/catch_compare_traits.hpp
index 6304b1ff..b0b501d9 100644
--- a/src/catch2/internal/catch_compare_traits.hpp
+++ b/src/catch2/internal/catch_compare_traits.hpp
@@ -35,21 +35,40 @@ namespace Catch {
# pragma clang diagnostic ignored "-Wfloat-equal"
#endif
+ // To avoid instantiating all of `is_foo_comparable<T, T&>`,
+ // `is_foo_comparable<T&, T&>`, `is_foo_comparable<T, T>`, ...
+ // we force the type into simple T ref. This does not cause behaviour
+ // change, because the decomposer already only uses lvalues.
+ //
+ // Note that we do not strip away constness, as that would make
+ // the comparability of `const T` dependent on comparability of `T`,
+ // which could lead to behavior change from the current implementation.
+ template <typename T>
+ using IsComparableNormalized_t = std::remove_reference_t<T>&;
+
#define CATCH_DEFINE_COMPARABLE_TRAIT( id, op ) \
template <typename, typename, typename = void> \
- struct is_##id##_comparable : std::false_type {}; \
+ struct is_##id##_comparable_impl : std::false_type {}; \
template <typename T, typename U> \
- struct is_##id##_comparable< \
+ struct is_##id##_comparable_impl< \
T, \
U, \
void_t<decltype( std::declval<T>() op std::declval<U>() )>> \
: std::true_type {}; \
+ template <typename T, typename U> \
+ using is_##id##_comparable = \
+ is_##id##_comparable_impl<IsComparableNormalized_t<T>, \
+ IsComparableNormalized_t<U>>; \
template <typename, typename = void> \
- struct is_##id##_0_comparable : std::false_type {}; \
+ struct is_##id##_0_comparable_impl : std::false_type {}; \
+ template <typename T> \
+ struct is_##id##_0_comparable_impl< \
+ T, \
+ void_t<decltype( std::declval<T>() op 0 )>> \
+ : std::true_type {}; \
template <typename T> \
- struct is_##id##_0_comparable<T, \
- void_t<decltype( std::declval<T>() op 0 )>> \
- : std::true_type {};
+ using is_##id##_0_comparable = \
+ is_##id##_0_comparable_impl<IsComparableNormalized_t<T>>;
// We need all 6 pre-spaceship comparison ops: <, <=, >, >=, ==, !=
CATCH_DEFINE_COMPARABLE_TRAIT( lt, < )