From 291c502f6676b8d304b608f936ec26e3b347054a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 20 Nov 2022 11:06:45 +0100 Subject: [PATCH] Fix old GCC + types with ambiguous constructor from 0 Closes #2571 --- src/catch2/internal/catch_decomposer.hpp | 103 +++++++++--------- .../SelfTest/UsageTests/Compilation.tests.cpp | 26 +++++ 2 files changed, 78 insertions(+), 51 deletions(-) diff --git a/src/catch2/internal/catch_decomposer.hpp b/src/catch2/internal/catch_decomposer.hpp index 3448803fe2..aec5f1e2ea 100644 --- a/src/catch2/internal/catch_decomposer.hpp +++ b/src/catch2/internal/catch_decomposer.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -168,19 +169,20 @@ namespace Catch { template < \ typename RhsT, \ std::enable_if_t< \ - Detail::is_##id##_comparable::value && \ - !std::is_arithmetic>::value, \ + Detail::conjunction, \ + Detail::negation>>>::value, \ int> = 0> \ friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \ ->BinaryExpr { \ return { \ static_cast( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ } \ - template < \ - typename RhsT, \ - std::enable_if_t::value && \ - std::is_arithmetic::value, \ - int> = 0> \ + template , \ + std::is_arithmetic>::value, \ + int> = 0> \ friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ ->BinaryExpr { \ return { \ @@ -188,59 +190,58 @@ namespace Catch { } \ template < \ typename RhsT, \ - std::enable_if_t::value && \ - Detail::is_eq_0_comparable:: \ - value && /* We allow long because we want \ - `ptr op NULL to be accepted */ \ - ( std::is_same::value || \ - std::is_same::value ), \ - int> = 0> \ + std::enable_if_t< \ + Detail::conjunction< \ + Detail::negation>, \ + Detail::is_eq_0_comparable, \ + Detail::disjunction, \ + /* On some platforms `NULL` is a long */ \ + std::is_same>>::value, \ + int> = 0> \ friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ ->BinaryExpr { \ - if ( rhs != 0 ) { \ - throw_test_failure_exception(); \ - } \ + if ( rhs != 0 ) { throw_test_failure_exception(); } \ return { \ static_cast( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \ } \ template < \ typename RhsT, \ - std::enable_if_t::value && \ - Detail::is_eq_0_comparable:: \ - value && /* We allow long because we want \ - `ptr op NULL` to be accepted */ \ - ( std::is_same::value || \ - std::is_same::value ), \ - int> = 0> \ + std::enable_if_t< \ + Detail::conjunction< \ + Detail::negation>, \ + Detail::is_eq_0_comparable, \ + Detail::disjunction, \ + /* On some platforms `NULL` is a long */ \ + std::is_same>>::value, \ + int> = 0> \ friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ ->BinaryExpr { \ - if ( lhs.m_lhs != 0 ) { \ - throw_test_failure_exception(); \ - } \ + if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); } \ return { static_cast( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ } CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( eq, == ) CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( ne, != ) - #undef CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR +#undef CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR - #define CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( id, op ) \ +#define CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( id, op ) \ template < \ typename RhsT, \ std::enable_if_t< \ - Detail::is_##id##_comparable::value && \ - !std::is_arithmetic>::value, \ + Detail::conjunction, \ + Detail::negation>>>::value, \ int> = 0> \ friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \ ->BinaryExpr { \ return { \ static_cast( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ } \ - template < \ - typename RhsT, \ - std::enable_if_t::value && \ - std::is_arithmetic::value, \ - int> = 0> \ + template , \ + std::is_arithmetic>::value, \ + int> = 0> \ friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ ->BinaryExpr { \ return { \ @@ -248,29 +249,29 @@ namespace Catch { } \ template < \ typename RhsT, \ - std::enable_if_t::value && \ - Detail::is_##id##_0_comparable::value && \ - std::is_same::value, \ - int> = 0> \ + std::enable_if_t< \ + Detail::conjunction< \ + Detail::negation>, \ + Detail::is_##id##_0_comparable, \ + std::is_same>::value, \ + int> = 0> \ friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ ->BinaryExpr { \ - if ( rhs != 0 ) { \ - throw_test_failure_exception(); \ - } \ + if ( rhs != 0 ) { throw_test_failure_exception(); } \ return { \ static_cast( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \ } \ template < \ typename RhsT, \ - std::enable_if_t::value && \ - Detail::is_##id##_0_comparable::value && \ - std::is_same::value, \ - int> = 0> \ + std::enable_if_t< \ + Detail::conjunction< \ + Detail::negation>, \ + Detail::is_##id##_0_comparable, \ + std::is_same>::value, \ + int> = 0> \ friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ ->BinaryExpr { \ - if ( lhs.m_lhs != 0 ) { \ - throw_test_failure_exception(); \ - } \ + if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); } \ return { static_cast( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ } @@ -279,7 +280,7 @@ namespace Catch { CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( gt, > ) CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( ge, >= ) - #undef CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR +#undef CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR #define CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(op) \ diff --git a/tests/SelfTest/UsageTests/Compilation.tests.cpp b/tests/SelfTest/UsageTests/Compilation.tests.cpp index a61a9674b6..a7b32df9f7 100644 --- a/tests/SelfTest/UsageTests/Compilation.tests.cpp +++ b/tests/SelfTest/UsageTests/Compilation.tests.cpp @@ -329,3 +329,29 @@ TEST_CASE( "#2555 - types that can only be compared with 0 literal (not int/long REQUIRE( TypeWithLit0Comparisons{} != 0 ); REQUIRE_FALSE( 0 != TypeWithLit0Comparisons{} ); } + +namespace { + struct MultipleImplicitConstructors { + MultipleImplicitConstructors( double ) {} + MultipleImplicitConstructors( int64_t ) {} + + bool operator==( MultipleImplicitConstructors ) const { return true; } + bool operator!=( MultipleImplicitConstructors ) const { return true; } + bool operator<( MultipleImplicitConstructors ) const { return true; } + bool operator<=( MultipleImplicitConstructors ) const { return true; } + bool operator>( MultipleImplicitConstructors ) const { return true; } + bool operator>=( MultipleImplicitConstructors ) const { return true; } + }; +} + +TEST_CASE("#2571 - tests compile types that have multiple implicit constructors from lit 0", + "[compilation][approvals]") { + MultipleImplicitConstructors mic1( 0.0 ); + MultipleImplicitConstructors mic2( 0.0 ); + REQUIRE( mic1 == mic2 ); + REQUIRE( mic1 != mic2 ); + REQUIRE( mic1 < mic2 ); + REQUIRE( mic1 <= mic2 ); + REQUIRE( mic1 > mic2 ); + REQUIRE( mic1 >= mic2 ); +}