diff --git a/include/cpp2util.h b/include/cpp2util.h index 1ee0a06f76..41bbb9beb9 100644 --- a/include/cpp2util.h +++ b/include/cpp2util.h @@ -2083,28 +2083,22 @@ auto as(X&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto) // is Type // -template - requires (std::is_same_v && !std::is_same_v && !std::is_same_v) -constexpr auto is( X const& x ) -> bool - { return x.type() == Typeid(); } - -template - requires (std::is_same_v && std::is_same_v) -constexpr auto is( X const& x ) -> bool - { return !x.has_value(); } - +template X> +constexpr auto is( X const& x ) -> bool{ + if (!x.has_value()) { + return std::is_same_v; + } + return x.type() == Typeid(); +} // is Value // inline constexpr auto is( std::any const& x, auto&& value ) -> bool { // Predicate case - if constexpr (requires{ bool{ value(x) }; }) { + if constexpr (valid_predicate) { return value(x); } - else if constexpr (std::is_function_v || requires{ &value.operator(); }) { - return false; - } // Value case else if constexpr (requires{ bool{ *std::any_cast(&x) == value }; }) { @@ -2118,10 +2112,12 @@ inline constexpr auto is( std::any const& x, auto&& value ) -> bool // as // -template - requires (!std::is_reference_v && std::is_same_v && !std::is_same_v) -constexpr auto as( X const& x ) -> T - { return std::any_cast( x ); } +template X> +constexpr auto as( X && x ) -> decltype(auto) { + constness_like_t* ptr = std::any_cast( &x ); + if (!ptr) { Throw( std::bad_any_cast(), "'as' cast failed for 'std::any'"); } + return cpp2::forward_like(*ptr); +} //------------------------------------------------------------------------------------------------------------- @@ -2130,16 +2126,16 @@ constexpr auto as( X const& x ) -> T // is Type // -template - requires std::is_same_v> -constexpr auto is( X const& x ) -> bool - { return x.has_value(); } - -template - requires std::is_same_v -constexpr auto is( std::optional const& x ) -> bool - { return !x.has_value(); } - +template X> +constexpr auto is( X const& x ) -> bool { + if (!x.has_value()) { + return std::same_as; + } + if constexpr (requires { static_cast(*x);}) { + return true; + } + return false; +} // is Value // @@ -2147,12 +2143,9 @@ template constexpr auto is( std::optional const& x, auto&& value ) -> bool { // Predicate case - if constexpr (requires{ bool{ value(x) }; }) { + if constexpr (valid_predicate) { return value(x); } - else if constexpr (std::is_function_v || requires{ &value.operator(); }) { - return false; - } // Value case else if constexpr (requires{ bool{ x.value() == value }; }) { @@ -2164,10 +2157,17 @@ constexpr auto is( std::optional const& x, auto&& value ) -> bool // as // -template - requires std::is_same_v> -constexpr auto as( X const& x ) -> decltype(auto) - { return x.value(); } +template X> +constexpr auto as( X&& x ) -> decltype(auto) { + constness_like_t* ptr = nullptr; + if constexpr (requires { static_cast&>(*x); }) { + if (x.has_value()) { + ptr = &static_cast&>(*x); + } + } + if (!ptr) { Throw( std::bad_optional_access(), "'as' cast failed for 'std::optional'"); } + return cpp2::forward_like(*ptr); +} } // impl diff --git a/regression-tests/test-results/gcc-10-c++20/pure2-default-arguments.cpp.output b/regression-tests/test-results/gcc-10-c++20/pure2-default-arguments.cpp.output index 7ed50a83d1..b6358b20cd 100644 --- a/regression-tests/test-results/gcc-10-c++20/pure2-default-arguments.cpp.output +++ b/regression-tests/test-results/gcc-10-c++20/pure2-default-arguments.cpp.output @@ -1,66 +1,66 @@ In file included from pure2-default-arguments.cpp:7: ../../../include/cpp2util.h:2086:28: error: local variable ‘obj’ may not appear in this context - 2086 | template + 2086 | template X> | ^~~ ../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’ 2047 | return false; | ^ ../../../include/cpp2util.h:2086:15: note: in expansion of macro ‘CPP2_FORWARD’ - 2086 | template + 2086 | template X> | ^~~~~~~~~~~~ ../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’ 2107 | } | ^ ../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’ - 2137 | + 2137 | return false; | ^ pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ ../../../include/cpp2util.h:2086:92: error: local variable ‘params’ may not appear in this context - 2086 | template + 2086 | template X> | ^ ../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’ 2047 | return false; | ^ ../../../include/cpp2util.h:2086:79: note: in expansion of macro ‘CPP2_FORWARD’ - 2086 | template + 2086 | template X> | ^ ../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’ 2107 | } | ^ ../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’ - 2137 | + 2137 | return false; | ^ pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ ../../../include/cpp2util.h:2087:74: error: local variable ‘obj’ may not appear in this context - 2087 | requires (std::is_same_v && !std::is_same_v && !std::is_same_v) - | ^~~ + 2087 | constexpr auto is( X const& x ) -> bool{ + | ^ ../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’ 2047 | return false; | ^ ../../../include/cpp2util.h:2087:61: note: in expansion of macro ‘CPP2_FORWARD’ - 2087 | requires (std::is_same_v && !std::is_same_v && !std::is_same_v) - | ^~~~~~~~~~~~ + 2087 | constexpr auto is( X const& x ) -> bool{ + | ^ ../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’ 2107 | } | ^ ../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’ - 2137 | + 2137 | return false; | ^ pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ ../../../include/cpp2util.h:2087:93: error: local variable ‘params’ may not appear in this context - 2087 | requires (std::is_same_v && !std::is_same_v && !std::is_same_v) - | ^~~~~~ + 2087 | constexpr auto is( X const& x ) -> bool{ + | ^ ../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’ 2047 | return false; | ^ ../../../include/cpp2util.h:2087:80: note: in expansion of macro ‘CPP2_FORWARD’ - 2087 | requires (std::is_same_v && !std::is_same_v && !std::is_same_v) - | ^~~~~~~~~~~~ + 2087 | constexpr auto is( X const& x ) -> bool{ + | ^ ../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’ 2107 | } | ^ ../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’ - 2137 | + 2137 | return false; | ^ pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ pure2-default-arguments.cpp2:6:61: error: ‘std::source_location’ has not been declared diff --git a/regression-tests/test-results/gcc-13-c++2b/mixed-bugfix-for-ufcs-non-local.cpp.output b/regression-tests/test-results/gcc-13-c++2b/mixed-bugfix-for-ufcs-non-local.cpp.output index b08a69eb07..20b01c3432 100644 --- a/regression-tests/test-results/gcc-13-c++2b/mixed-bugfix-for-ufcs-non-local.cpp.output +++ b/regression-tests/test-results/gcc-13-c++2b/mixed-bugfix-for-ufcs-non-local.cpp.output @@ -1,41 +1,41 @@ In file included from mixed-bugfix-for-ufcs-non-local.cpp:6: ../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type - 2100 | { + 2100 | return value(x); | ^ ../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’ - 2137 | + 2137 | return false; | ^ mixed-bugfix-for-ufcs-non-local.cpp2:13:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:13:36: error: template argument 1 is invalid ../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type - 2100 | { + 2100 | return value(x); | ^ ../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’ - 2137 | + 2137 | return false; | ^ mixed-bugfix-for-ufcs-non-local.cpp2:21:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:21:36: error: template argument 1 is invalid ../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type - 2100 | { + 2100 | return value(x); | ^ ../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’ - 2137 | + 2137 | return false; | ^ mixed-bugfix-for-ufcs-non-local.cpp2:31:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:31:36: error: template argument 1 is invalid ../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type - 2100 | { + 2100 | return value(x); | ^ ../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’ - 2137 | + 2137 | return false; | ^ mixed-bugfix-for-ufcs-non-local.cpp2:33:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:33:36: error: template argument 1 is invalid ../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type - 2100 | { + 2100 | return value(x); | ^ ../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’ - 2137 | + 2137 | return false; | ^ mixed-bugfix-for-ufcs-non-local.cpp2:21:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:21:36: error: template argument 1 is invalid diff --git a/regression-tests/test-results/gcc-14-c++2b/mixed-bugfix-for-ufcs-non-local.cpp.output b/regression-tests/test-results/gcc-14-c++2b/mixed-bugfix-for-ufcs-non-local.cpp.output index b08a69eb07..20b01c3432 100644 --- a/regression-tests/test-results/gcc-14-c++2b/mixed-bugfix-for-ufcs-non-local.cpp.output +++ b/regression-tests/test-results/gcc-14-c++2b/mixed-bugfix-for-ufcs-non-local.cpp.output @@ -1,41 +1,41 @@ In file included from mixed-bugfix-for-ufcs-non-local.cpp:6: ../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type - 2100 | { + 2100 | return value(x); | ^ ../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’ - 2137 | + 2137 | return false; | ^ mixed-bugfix-for-ufcs-non-local.cpp2:13:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:13:36: error: template argument 1 is invalid ../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type - 2100 | { + 2100 | return value(x); | ^ ../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’ - 2137 | + 2137 | return false; | ^ mixed-bugfix-for-ufcs-non-local.cpp2:21:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:21:36: error: template argument 1 is invalid ../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type - 2100 | { + 2100 | return value(x); | ^ ../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’ - 2137 | + 2137 | return false; | ^ mixed-bugfix-for-ufcs-non-local.cpp2:31:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:31:36: error: template argument 1 is invalid ../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type - 2100 | { + 2100 | return value(x); | ^ ../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’ - 2137 | + 2137 | return false; | ^ mixed-bugfix-for-ufcs-non-local.cpp2:33:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:33:36: error: template argument 1 is invalid ../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type - 2100 | { + 2100 | return value(x); | ^ ../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’ - 2137 | + 2137 | return false; | ^ mixed-bugfix-for-ufcs-non-local.cpp2:21:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:21:36: error: template argument 1 is invalid