diff --git a/include/cpp2util.h b/include/cpp2util.h index dee5bd2a9..4aead2ae1 100644 --- a/include/cpp2util.h +++ b/include/cpp2util.h @@ -2078,6 +2078,93 @@ constexpr auto as( X&& x ) -> decltype(auto) { } + +//------------------------------------------------------------------------------------------------------------- +// std::expected is and as +// +#ifdef __cpp_lib_expected + +// 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::expected const& x) -> bool +{ + return !x.has_value(); +} + +// is std::unexpected Type +// +template + requires ( + std::is_same_v> + && std::is_same_v> + ) +constexpr auto is(X const& x) -> bool +{ + return !x.has_value(); +} + + +// is Value +// +template +constexpr auto is(std::expected const& x, auto&& value) -> bool +{ + // Predicate case + if constexpr (requires{ bool{ value(x) }; }) { + 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 }; }) { + return x.has_value() && x.value() == value; + } + else { + return false; + } +} + + +// as +// +template + requires std::is_same_v> +constexpr auto as(X const& x) -> decltype(auto) +{ + return x.value(); +} + +// as std::unexpected +// +template + requires ( + std::is_same_v> + && std::is_same_v> + ) +constexpr auto as(X const& x) -> decltype(auto) +{ + // It's UB to call `error` if `has_value` is true. + if (x.has_value()) { + Throw( + std::runtime_error("Cannot cast 'expected' to 'unexpected' because it has a value"), + "Cannot cast 'expected' to 'unexpected' because it has a value"); + } + + return std::unexpected(x.error()); +} +#endif + } // impl diff --git a/regression-tests/pure2-expected-is-as.cpp2 b/regression-tests/pure2-expected-is-as.cpp2 new file mode 100644 index 000000000..d144b2770 --- /dev/null +++ b/regression-tests/pure2-expected-is-as.cpp2 @@ -0,0 +1,90 @@ +// `std::expected` requires C++23 so a dedicated test file is needed +// since only MSVC supports it at time of writing, and there's no #ifdef +// or `static if` support in Cpp2 (yet?). + +main: () -> int = { + + ex1: std::expected = (123); + ex2: std::expected = std::unexpected(-1); + ex3: std::expected = ("Expect the unexpected"); + + if ex1 is int { + std::cout << "ex1 is int\n"; + } + + if ex1 is bool { + std::cout << "BUG - ex1 is not a bool\n"; + return -1; + } + + if ex1 is void { + std::cout << "BUG - ex1 is not 'empty'\n"; + return -1; + } + + if ex1 is std::unexpected { + std::cout << "BUG - ex1 is not unexpected\n"; + return -1; + } + + if ex1 is 123 { + std::cout << "ex1 is 123\n"; + } + + if ex1 is 100 { + std::cout << "BUG - ex1's value is not 100\n"; + return -1; + } + + val1:= ex1 as int; + std::cout << "ex1 as int = " << val1 << "\n"; + + if ex2 is int { + std::cout << "BUG - ex2 is not an int\n"; + return -1; + } + + if ex2 is bool { + std::cout << "BUG - ex2 is not a bool\n"; + return -1; + } + + if ex2 is 123 { + std::cout << "BUG - ex2 does not have a value\n"; + return -1; + } + + if ex2 is std::unexpected { + std::cout << "ex2 is unexpected and error is: " << ex2.error() << "\n"; + } + + if ex2 is void { + std::cout << "ex2 is 'empty' aka unexpected and error is: " << ex2.error() << "\n"; + } + + ex2_err:= ex2 as std::unexpected; + std::cout << "ex2 as std::unexpected and error = " << ex2_err.error() << "\n"; + + test_inspect(ex1, "expected with value"); + test_inspect(ex2, "expected with unexpected"); + test_inspect(ex3, "expected with value"); + + return 0; +} + +test_inspect: ( x: _, msg: _ ) = { + + unwrap:= :(unexp: std::unexpected) -> _ = { + return unexp.error(); + }; + + std::cout + << "\n" << msg << "\n ..." + << inspect x -> std::string { + is int = "integer " + std::to_string(x as int); + is std::unexpected = "unexpected " + std::to_string(unwrap(x as std::unexpected)); + is std::string = "string " + x as std::string; + is _ = " no match"; + } + << "\n"; +} \ No newline at end of file diff --git a/regression-tests/run-tests.sh b/regression-tests/run-tests.sh index b4cfc8787..6e3ac81b7 100644 --- a/regression-tests/run-tests.sh +++ b/regression-tests/run-tests.sh @@ -135,28 +135,11 @@ if [ -z "$label" ]; then usage fi -tests=$(ls | grep ".cpp2$") -if [[ -n "$chosen_tests" ]]; then - for test in $chosen_tests; do - if ! [[ -f "$test" ]]; then - echo "Requested test ($test) not found" - exit 1 - fi - done - echo "Performing tests:" - for test in $chosen_tests; do - echo " $test" - done - echo - tests="$chosen_tests" -else - printf "Performing all regression tests\n\n" -fi - -expected_results_dir="test-results" - ################ # Get the directory with the exec outputs and compilation command +# We also allow each compiler configuration to specify any test files(s) to exclude from running. +expected_results_dir="test-results" +exclude_test_filter="" if [[ "$cxx_compiler" == *"cl.exe"* ]]; then compiler_cmd="cl.exe -nologo -std:${cxx_std} -MD -EHsc -I ..\..\..\include -Fe:" exec_out_dir="$expected_results_dir/msvc-2022-${cxx_std}" @@ -174,6 +157,12 @@ else if [[ "$compiler_version" == *"Apple clang version 14.0"* || "$compiler_version" == *"Homebrew clang version 15.0"* ]]; then exec_out_dir="$expected_results_dir/apple-clang-14" + # We share the expected results dir for these two compilers, but there is one + # test which (as expected) fails to compile on both compilers, but has a slightly + # different error diagnostic because the clang path differs. So we exclude it from + # running. The alternative would be to duplicate the expected results files, which + # seems wasteful for just one test (that doesn't even compile). + exclude_test_filter="pure2-expected-is-as.cpp2" elif [[ "$compiler_version" == *"Apple clang version 15.0"* ]]; then exec_out_dir="$expected_results_dir/apple-clang-15" elif [[ "$compiler_version" == *"clang version 12.0"* ]]; then @@ -236,6 +225,30 @@ else exit 2 fi +################ +# Get the list of .cpp2 test files +if [[ -n "$exclude_test_filter" ]]; then + tests=$(ls | grep ".cpp2$" | grep -v $exclude_test_filter) +else + tests=$(ls | grep ".cpp2$") +fi +if [[ -n "$chosen_tests" ]]; then + for test in $chosen_tests; do + if ! [[ -f "$test" ]]; then + echo "Requested test ($test) not found" + exit 1 + fi + done + echo "Performing tests:" + for test in $chosen_tests; do + echo " $test" + done + echo + tests="$chosen_tests" +else + printf "Performing all regression tests\n\n" +fi + ################ cppfront_cmd="cppfront.exe" echo "Building cppfront" diff --git a/regression-tests/test-results/apple-clang-14-c++2b/pure2-expected-is-as.cpp.output b/regression-tests/test-results/apple-clang-14-c++2b/pure2-expected-is-as.cpp.output new file mode 100644 index 000000000..7280779fa --- /dev/null +++ b/regression-tests/test-results/apple-clang-14-c++2b/pure2-expected-is-as.cpp.output @@ -0,0 +1,63 @@ +pure2-expected-is-as.cpp2:7:10: error: no member named 'expected' in namespace 'std' + std::expected ex1 {123}; + ~~~~~^ +pure2-expected-is-as.cpp2:7:22: error: expected '(' for function-style cast or type construction + std::expected ex1 {123}; + ~~~^ +pure2-expected-is-as.cpp2:8:10: error: no member named 'expected' in namespace 'std' + std::expected ex2 {std::unexpected(-1)}; + ~~~~~^ +pure2-expected-is-as.cpp2:8:22: error: expected '(' for function-style cast or type construction + std::expected ex2 {std::unexpected(-1)}; + ~~~^ +pure2-expected-is-as.cpp2:9:10: error: no member named 'expected' in namespace 'std' + std::expected ex3 {"Expect the unexpected"}; + ~~~~~^ +pure2-expected-is-as.cpp2:9:30: error: expected '(' for function-style cast or type construction + std::expected ex3 {"Expect the unexpected"}; + ~~~~~~~~~~~^ +pure2-expected-is-as.cpp2:11:29: error: use of undeclared identifier 'ex1' + if (cpp2::impl::is(ex1)) { + ^ +pure2-expected-is-as.cpp2:15:30: error: use of undeclared identifier 'ex1' + if (cpp2::impl::is(ex1)) { + ^ +pure2-expected-is-as.cpp2:20:30: error: use of undeclared identifier 'ex1' + if (cpp2::impl::is(ex1)) { + ^ +pure2-expected-is-as.cpp2:25:29: error: no member named 'unexpected' in namespace 'std' + if (cpp2::impl::is>(ex1)) { + ~~~~~^ +pure2-expected-is-as.cpp2:25:43: error: expected '(' for function-style cast or type construction + if (cpp2::impl::is>(ex1)) { + ~~~^ +pure2-expected-is-as.cpp2:25:46: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + if (cpp2::impl::is>(ex1)) { + ^~~ + exp +/Applications/Xcode_14.3.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/math.h:895:1: note: 'exp' declared here +exp(_A1 __lcpp_x) _NOEXCEPT {return ::exp((double)__lcpp_x);} +^ +pure2-expected-is-as.cpp2:30:24: error: use of undeclared identifier 'ex1' + if (cpp2::impl::is(ex1, 123)) { + ^ +pure2-expected-is-as.cpp2:34:24: error: use of undeclared identifier 'ex1' + if (cpp2::impl::is(ex1, 100)) { + ^ +pure2-expected-is-as.cpp2:39:37: error: use of undeclared identifier 'ex1' + auto val1 {cpp2::impl::as_(ex1)}; + ^ +pure2-expected-is-as.cpp2:42:29: error: use of undeclared identifier 'ex2' + if (cpp2::impl::is(ex2)) { + ^ +pure2-expected-is-as.cpp2:47:30: error: use of undeclared identifier 'ex2' + if (cpp2::impl::is(ex2)) { + ^ +pure2-expected-is-as.cpp2:52:24: error: use of undeclared identifier 'ex2' + if (cpp2::impl::is(ex2, 123)) { + ^ +pure2-expected-is-as.cpp2:57:29: error: no member named 'unexpected' in namespace 'std' + if (cpp2::impl::is>(ex2)) { + ~~~~~^ +fatal error: too many errors emitted, stopping now [-ferror-limit=] +20 errors generated. diff --git a/regression-tests/test-results/apple-clang-15-c++2b/pure2-expected-is-as.cpp.execution b/regression-tests/test-results/apple-clang-15-c++2b/pure2-expected-is-as.cpp.execution new file mode 100644 index 000000000..5483d6cd7 --- /dev/null +++ b/regression-tests/test-results/apple-clang-15-c++2b/pure2-expected-is-as.cpp.execution @@ -0,0 +1,15 @@ +ex1 is int +ex1 is 123 +ex1 as int = 123 +ex2 is unexpected and error is: -1 +ex2 is 'empty' aka unexpected and error is: -1 +ex2 as std::unexpected and error = -1 + +expected with value + ...integer 123 + +expected with unexpected + ...unexpected -1 + +expected with value + ...string Expect the unexpected diff --git a/regression-tests/test-results/clang-12-c++20/pure2-expected-is-as.cpp.output b/regression-tests/test-results/clang-12-c++20/pure2-expected-is-as.cpp.output new file mode 100644 index 000000000..78c70e989 --- /dev/null +++ b/regression-tests/test-results/clang-12-c++20/pure2-expected-is-as.cpp.output @@ -0,0 +1,169 @@ +pure2-expected-is-as.cpp2:7:22: error: expected '(' for function-style cast or type construction + std::expected ex1 {123}; + ~~~^ +pure2-expected-is-as.cpp2:7:10: error: no member named 'expected' in namespace 'std'; did you mean 'unexpected'? + std::expected ex1 {123}; + ~~~~~^~~~~~~~ + unexpected +/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/exception:92:8: note: 'unexpected' declared here + void unexpected() __attribute__ ((__noreturn__)); + ^ +pure2-expected-is-as.cpp2:8:22: error: expected '(' for function-style cast or type construction + std::expected ex2 {std::unexpected(-1)}; + ~~~^ +pure2-expected-is-as.cpp2:8:10: error: no member named 'expected' in namespace 'std'; did you mean 'unexpected'? + std::expected ex2 {std::unexpected(-1)}; + ~~~~~^~~~~~~~ + unexpected +/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/exception:92:8: note: 'unexpected' declared here + void unexpected() __attribute__ ((__noreturn__)); + ^ +pure2-expected-is-as.cpp2:9:30: error: expected '(' for function-style cast or type construction + std::expected ex3 {"Expect the unexpected"}; + ~~~~~~~~~~~^ +pure2-expected-is-as.cpp2:9:10: error: no member named 'expected' in namespace 'std'; did you mean 'unexpected'? + std::expected ex3 {"Expect the unexpected"}; + ~~~~~^~~~~~~~ + unexpected +/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/exception:92:8: note: 'unexpected' declared here + void unexpected() __attribute__ ((__noreturn__)); + ^ +pure2-expected-is-as.cpp2:11:29: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + if (cpp2::impl::is(ex1)) { + ^~~ + exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here +__MATHCALL_VEC (exp,, (_Mdouble_ __x)); + ^ +pure2-expected-is-as.cpp2:15:30: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + if (cpp2::impl::is(ex1)) { + ^~~ + exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here +__MATHCALL_VEC (exp,, (_Mdouble_ __x)); + ^ +pure2-expected-is-as.cpp2:20:30: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + if (cpp2::impl::is(ex1)) { + ^~~ + exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here +__MATHCALL_VEC (exp,, (_Mdouble_ __x)); + ^ +pure2-expected-is-as.cpp2:25:29: error: 'unexpected' does not name a template but is followed by template arguments + if (cpp2::impl::is>(ex1)) { + ^ ~~~~~ +/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/exception:92:8: note: non-template declaration found by name lookup + void unexpected() __attribute__ ((__noreturn__)); + ^ +pure2-expected-is-as.cpp2:25:46: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + if (cpp2::impl::is>(ex1)) { + ^~~ + exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here +__MATHCALL_VEC (exp,, (_Mdouble_ __x)); + ^ +pure2-expected-is-as.cpp2:30:24: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + if (cpp2::impl::is(ex1, 123)) { + ^~~ + exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here +__MATHCALL_VEC (exp,, (_Mdouble_ __x)); + ^ +pure2-expected-is-as.cpp2:34:24: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + if (cpp2::impl::is(ex1, 100)) { + ^~~ + exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here +__MATHCALL_VEC (exp,, (_Mdouble_ __x)); + ^ +In file included from pure2-expected-is-as.cpp:7: +../../../include/cpp2util.h:1770:72: error: invalid application of 'sizeof' to a function type + (std::is_floating_point_v && std::is_floating_point_v && sizeof(From) > sizeof(To)) || // NOLINT(misc-redundant-expression) + ^~~~~~~~~~~~ +../../../include/cpp2util.h:2891:19: note: in instantiation of variable template specialization 'cpp2::impl::is_narrowing_v' requested here + if constexpr (is_narrowing_v) { + ^ +pure2-expected-is-as.cpp2:39:28: note: in instantiation of function template specialization 'cpp2::impl::as_' requested here + auto val1 {cpp2::impl::as_(ex1)}; + ^ +In file included from pure2-expected-is-as.cpp:7: +../../../include/cpp2util.h:2911:12: error: no matching function for call to 'as' + return as(CPP2_FORWARD(x)); + ^~~~~ +pure2-expected-is-as.cpp2:39:28: note: in instantiation of function template specialization 'cpp2::impl::as_' requested here + auto val1 {cpp2::impl::as_(ex1)}; + ^ +../../../include/cpp2util.h:1838:16: note: candidate template ignored: constraints not satisfied [with C = int, x:auto = double (&)(double) noexcept] +constexpr auto as(auto&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto) + ^ +../../../include/cpp2util.h:1844:18: note: because 'std::is_scalar_v >' evaluated to false + (std::is_scalar_v && !std::is_enum_v) + ^ +../../../include/cpp2util.h:1845:17: note: and 'std::is_floating_point_v >' evaluated to false + || std::is_floating_point_v + ^ +../../../include/cpp2util.h:1846:17: note: and 'std::is_base_of_v >' evaluated to false + || std::is_base_of_v + ^ +../../../include/cpp2util.h:1847:17: note: and 'std::is_base_of_v, int>' evaluated to false + || std::is_base_of_v + ^ +../../../include/cpp2util.h:1848:30: note: and 'C({std::forward(x)})' would be invalid: cannot initialize a value of type 'int' with an lvalue of type 'double (double) noexcept' + || requires { C{CPP2_FORWARD(x)}; } + ^ +../../../include/cpp2util.h:325:37: note: expanded from macro 'CPP2_FORWARD' +#define CPP2_FORWARD(x) std::forward(x) + ^ +../../../include/cpp2util.h:1977:6: note: candidate template ignored: constraints not satisfied [with C = int, X = double (&)(double) noexcept] +auto as(X&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto) + ^ +../../../include/cpp2util.h:1976:23: note: because 'specialization_of_template' evaluated to false +template< typename C, specialization_of_template X > + ^ +../../../include/cpp2util.h:724:7: note: because 'specialization_of_template_helper(std::forward(x))' would be invalid: no matching function for call to 'specialization_of_template_helper' + { specialization_of_template_helper(std::forward(x)) } -> std::same_as; + ^ +../../../include/cpp2util.h:2024:16: note: candidate template ignored: constraints not satisfied [with T = int, X = double (&)(double) noexcept] +constexpr auto as( X && x ) -> decltype(auto) { + ^ +../../../include/cpp2util.h:2023:22: note: because 'same_type_as' evaluated to false +template X> + ^ +../../../include/cpp2util.h:754:29: note: because 'std::same_as, std::remove_cvref_t >' evaluated to false +concept same_type_as = std::same_as, std::remove_cvref_t>; + ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/concepts:63:19: note: because '__detail::__same_as' evaluated to false + = __detail::__same_as<_Tp, _Up> && __detail::__same_as<_Up, _Tp>; + ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/concepts:57:27: note: because 'std::is_same_v' evaluated to false + concept __same_as = std::is_same_v<_Tp, _Up>; + ^ +../../../include/cpp2util.h:2069:16: note: candidate template ignored: constraints not satisfied [with T = int, X = double (&)(double) noexcept] +constexpr auto as( X&& x ) -> decltype(auto) { + ^ +../../../include/cpp2util.h:2068:22: note: because 'specialization_of_template' evaluated to false +template X> + ^ +../../../include/cpp2util.h:724:7: note: because 'specialization_of_template_helper(std::forward(x))' would be invalid: no matching function for call to 'specialization_of_template_helper' + { specialization_of_template_helper(std::forward(x)) } -> std::same_as; + ^ +../../../include/cpp2util.h:1813:16: note: candidate function template not viable: requires 0 arguments, but 1 was provided +constexpr auto as() -> auto + ^ +../../../include/cpp2util.h:1824:16: note: candidate function template not viable: requires 0 arguments, but 1 was provided +constexpr auto as() -> auto + ^ +pure2-expected-is-as.cpp2:39:37: error: use of undeclared identifier 'ex1' + auto val1 {cpp2::impl::as_(ex1)}; + ^ +pure2-expected-is-as.cpp2:42:29: error: use of undeclared identifier 'ex2' + if (cpp2::impl::is(ex2)) { + ^ +pure2-expected-is-as.cpp2:47:30: error: use of undeclared identifier 'ex2' + if (cpp2::impl::is(ex2)) { + ^ +pure2-expected-is-as.cpp2:52:24: error: use of undeclared identifier 'ex2' + if (cpp2::impl::is(ex2, 123)) { + ^ +fatal error: too many errors emitted, stopping now [-ferror-limit=] +20 errors generated. diff --git a/regression-tests/test-results/clang-15-c++20-libcpp/pure2-expected-is-as.cpp.output b/regression-tests/test-results/clang-15-c++20-libcpp/pure2-expected-is-as.cpp.output new file mode 100644 index 000000000..657d2b8ed --- /dev/null +++ b/regression-tests/test-results/clang-15-c++20-libcpp/pure2-expected-is-as.cpp.output @@ -0,0 +1,63 @@ +pure2-expected-is-as.cpp2:7:10: error: no member named 'expected' in namespace 'std' + std::expected ex1 {123}; + ~~~~~^ +pure2-expected-is-as.cpp2:7:22: error: expected '(' for function-style cast or type construction + std::expected ex1 {123}; + ~~~^ +pure2-expected-is-as.cpp2:8:10: error: no member named 'expected' in namespace 'std' + std::expected ex2 {std::unexpected(-1)}; + ~~~~~^ +pure2-expected-is-as.cpp2:8:22: error: expected '(' for function-style cast or type construction + std::expected ex2 {std::unexpected(-1)}; + ~~~^ +pure2-expected-is-as.cpp2:9:10: error: no member named 'expected' in namespace 'std' + std::expected ex3 {"Expect the unexpected"}; + ~~~~~^ +pure2-expected-is-as.cpp2:9:30: error: expected '(' for function-style cast or type construction + std::expected ex3 {"Expect the unexpected"}; + ~~~~~~~~~~~^ +pure2-expected-is-as.cpp2:11:29: error: use of undeclared identifier 'ex1' + if (cpp2::impl::is(ex1)) { + ^ +pure2-expected-is-as.cpp2:15:30: error: use of undeclared identifier 'ex1' + if (cpp2::impl::is(ex1)) { + ^ +pure2-expected-is-as.cpp2:20:30: error: use of undeclared identifier 'ex1' + if (cpp2::impl::is(ex1)) { + ^ +pure2-expected-is-as.cpp2:25:29: error: no member named 'unexpected' in namespace 'std' + if (cpp2::impl::is>(ex1)) { + ~~~~~^ +pure2-expected-is-as.cpp2:25:43: error: expected '(' for function-style cast or type construction + if (cpp2::impl::is>(ex1)) { + ~~~^ +pure2-expected-is-as.cpp2:25:46: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + if (cpp2::impl::is>(ex1)) { + ^~~ + exp +/usr/lib/llvm-15/bin/../include/c++/v1/math.h:895:1: note: 'exp' declared here +exp(_A1 __lcpp_x) _NOEXCEPT {return ::exp((double)__lcpp_x);} +^ +pure2-expected-is-as.cpp2:30:24: error: use of undeclared identifier 'ex1' + if (cpp2::impl::is(ex1, 123)) { + ^ +pure2-expected-is-as.cpp2:34:24: error: use of undeclared identifier 'ex1' + if (cpp2::impl::is(ex1, 100)) { + ^ +pure2-expected-is-as.cpp2:39:37: error: use of undeclared identifier 'ex1' + auto val1 {cpp2::impl::as_(ex1)}; + ^ +pure2-expected-is-as.cpp2:42:29: error: use of undeclared identifier 'ex2' + if (cpp2::impl::is(ex2)) { + ^ +pure2-expected-is-as.cpp2:47:30: error: use of undeclared identifier 'ex2' + if (cpp2::impl::is(ex2)) { + ^ +pure2-expected-is-as.cpp2:52:24: error: use of undeclared identifier 'ex2' + if (cpp2::impl::is(ex2, 123)) { + ^ +pure2-expected-is-as.cpp2:57:29: error: no member named 'unexpected' in namespace 'std' + if (cpp2::impl::is>(ex2)) { + ~~~~~^ +fatal error: too many errors emitted, stopping now [-ferror-limit=] +20 errors generated. diff --git a/regression-tests/test-results/clang-15-c++20/pure2-expected-is-as.cpp.output b/regression-tests/test-results/clang-15-c++20/pure2-expected-is-as.cpp.output new file mode 100644 index 000000000..613220d97 --- /dev/null +++ b/regression-tests/test-results/clang-15-c++20/pure2-expected-is-as.cpp.output @@ -0,0 +1,245 @@ +pure2-expected-is-as.cpp2:7:22: error: expected '(' for function-style cast or type construction + std::expected ex1 {123}; + ~~~^ +pure2-expected-is-as.cpp2:7:10: error: no member named 'expected' in namespace 'std'; did you mean 'unexpected'? + std::expected ex1 {123}; + ~~~~~^~~~~~~~ + unexpected +/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/exception:109:8: note: 'unexpected' declared here + void unexpected() __attribute__ ((__noreturn__)); + ^ +pure2-expected-is-as.cpp2:8:22: error: expected '(' for function-style cast or type construction + std::expected ex2 {std::unexpected(-1)}; + ~~~^ +pure2-expected-is-as.cpp2:8:10: error: no member named 'expected' in namespace 'std'; did you mean 'unexpected'? + std::expected ex2 {std::unexpected(-1)}; + ~~~~~^~~~~~~~ + unexpected +/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/exception:109:8: note: 'unexpected' declared here + void unexpected() __attribute__ ((__noreturn__)); + ^ +pure2-expected-is-as.cpp2:9:30: error: expected '(' for function-style cast or type construction + std::expected ex3 {"Expect the unexpected"}; + ~~~~~~~~~~~^ +pure2-expected-is-as.cpp2:9:10: error: no member named 'expected' in namespace 'std'; did you mean 'unexpected'? + std::expected ex3 {"Expect the unexpected"}; + ~~~~~^~~~~~~~ + unexpected +/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/exception:109:8: note: 'unexpected' declared here + void unexpected() __attribute__ ((__noreturn__)); + ^ +pure2-expected-is-as.cpp2:11:29: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + if (cpp2::impl::is(ex1)) { + ^~~ + exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here +__MATHCALL_VEC (exp,, (_Mdouble_ __x)); + ^ +pure2-expected-is-as.cpp2:15:30: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + if (cpp2::impl::is(ex1)) { + ^~~ + exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here +__MATHCALL_VEC (exp,, (_Mdouble_ __x)); + ^ +pure2-expected-is-as.cpp2:20:30: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + if (cpp2::impl::is(ex1)) { + ^~~ + exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here +__MATHCALL_VEC (exp,, (_Mdouble_ __x)); + ^ +pure2-expected-is-as.cpp2:25:29: warning: 'unexpected' is deprecated [-Wdeprecated-declarations] + if (cpp2::impl::is>(ex1)) { + ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/exception:108:3: note: 'unexpected' has been explicitly marked deprecated here + _GLIBCXX11_DEPRECATED + ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/x86_64-linux-gnu/c++/12/bits/c++config.h:103:32: note: expanded from macro '_GLIBCXX11_DEPRECATED' +# define _GLIBCXX11_DEPRECATED _GLIBCXX_DEPRECATED + ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/x86_64-linux-gnu/c++/12/bits/c++config.h:94:46: note: expanded from macro '_GLIBCXX_DEPRECATED' +# define _GLIBCXX_DEPRECATED __attribute__ ((__deprecated__)) + ^ +pure2-expected-is-as.cpp2:25:29: error: 'unexpected' does not name a template but is followed by template arguments + if (cpp2::impl::is>(ex1)) { + ^ ~~~~~ +/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/exception:109:8: note: non-template declaration found by name lookup + void unexpected() __attribute__ ((__noreturn__)); + ^ +pure2-expected-is-as.cpp2:25:46: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + if (cpp2::impl::is>(ex1)) { + ^~~ + exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here +__MATHCALL_VEC (exp,, (_Mdouble_ __x)); + ^ +pure2-expected-is-as.cpp2:30:24: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + if (cpp2::impl::is(ex1, 123)) { + ^~~ + exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here +__MATHCALL_VEC (exp,, (_Mdouble_ __x)); + ^ +pure2-expected-is-as.cpp2:34:24: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + if (cpp2::impl::is(ex1, 100)) { + ^~~ + exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here +__MATHCALL_VEC (exp,, (_Mdouble_ __x)); + ^ +In file included from pure2-expected-is-as.cpp:7: +../../../include/cpp2util.h:1770:72: error: invalid application of 'sizeof' to a function type + (std::is_floating_point_v && std::is_floating_point_v && sizeof(From) > sizeof(To)) || // NOLINT(misc-redundant-expression) + ^~~~~~~~~~~~ +../../../include/cpp2util.h:2891:19: note: in instantiation of variable template specialization 'cpp2::impl::is_narrowing_v' requested here + if constexpr (is_narrowing_v) { + ^ +pure2-expected-is-as.cpp2:39:28: note: in instantiation of function template specialization 'cpp2::impl::as_' requested here + auto val1 {cpp2::impl::as_(ex1)}; + ^ +In file included from pure2-expected-is-as.cpp:7: +../../../include/cpp2util.h:2892:9: error: static assertion failed due to requirement 'program_violates_type_safety_guarantee': 'as' does not allow unsafe possibly-lossy narrowing conversions - if you're sure you want this, use 'unchecked_narrow' to explicitly force the conversion and possibly lose information + static_assert( + ^ +pure2-expected-is-as.cpp2:39:28: note: in instantiation of function template specialization 'cpp2::impl::as_' requested here + auto val1 {cpp2::impl::as_(ex1)}; + ^ +In file included from pure2-expected-is-as.cpp:7: +../../../include/cpp2util.h:2904:52: error: no matching function for call to 'as' + else if constexpr( std::is_same_v< CPP2_TYPEOF(as(CPP2_FORWARD(x))), nonesuch_ > ) { + ^~~~~ +../../../include/cpp2util.h:315:66: note: expanded from macro 'CPP2_TYPEOF' +#define CPP2_TYPEOF(x) std::remove_cvref_t + ^ +../../../include/cpp2util.h:1838:16: note: candidate template ignored: constraints not satisfied [with C = int, x:auto = double (&)(double) noexcept] +constexpr auto as(auto&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto) + ^ +../../../include/cpp2util.h:1844:18: note: because 'std::is_scalar_v >' evaluated to false + (std::is_scalar_v && !std::is_enum_v) + ^ +../../../include/cpp2util.h:1845:17: note: and 'std::is_floating_point_v >' evaluated to false + || std::is_floating_point_v + ^ +../../../include/cpp2util.h:1846:17: note: and 'std::is_base_of_v >' evaluated to false + || std::is_base_of_v + ^ +../../../include/cpp2util.h:1847:17: note: and 'std::is_base_of_v, int>' evaluated to false + || std::is_base_of_v + ^ +../../../include/cpp2util.h:1848:30: note: and 'C{std::forward(x)}' would be invalid: cannot initialize a value of type 'int' with an lvalue of type 'double (double) noexcept' + || requires { C{CPP2_FORWARD(x)}; } + ^ +../../../include/cpp2util.h:325:37: note: expanded from macro 'CPP2_FORWARD' +#define CPP2_FORWARD(x) std::forward(x) + ^ +../../../include/cpp2util.h:1977:6: note: candidate template ignored: constraints not satisfied [with C = int, X = double (&)(double) noexcept] +auto as(X&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto) + ^ +../../../include/cpp2util.h:1976:23: note: because 'specialization_of_template' evaluated to false +template< typename C, specialization_of_template X > + ^ +../../../include/cpp2util.h:724:7: note: because 'specialization_of_template_helper(std::forward(x))' would be invalid: no matching function for call to 'specialization_of_template_helper' + { specialization_of_template_helper(std::forward(x)) } -> std::same_as; + ^ +../../../include/cpp2util.h:2024:16: note: candidate template ignored: constraints not satisfied [with T = int, X = double (&)(double) noexcept] +constexpr auto as( X && x ) -> decltype(auto) { + ^ +../../../include/cpp2util.h:2023:22: note: because 'same_type_as' evaluated to false +template X> + ^ +../../../include/cpp2util.h:754:24: note: because 'std::same_as, std::remove_cvref_t >' evaluated to false +concept same_type_as = std::same_as, std::remove_cvref_t>; + ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/concepts:63:9: note: because '__detail::__same_as' evaluated to false + = __detail::__same_as<_Tp, _Up> && __detail::__same_as<_Up, _Tp>; + ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/concepts:57:27: note: because 'std::is_same_v' evaluated to false + concept __same_as = std::is_same_v<_Tp, _Up>; + ^ +../../../include/cpp2util.h:2069:16: note: candidate template ignored: constraints not satisfied [with T = int, X = double (&)(double) noexcept] +constexpr auto as( X&& x ) -> decltype(auto) { + ^ +../../../include/cpp2util.h:2068:22: note: because 'specialization_of_template' evaluated to false +template X> + ^ +../../../include/cpp2util.h:724:7: note: because 'specialization_of_template_helper(std::forward(x))' would be invalid: no matching function for call to 'specialization_of_template_helper' + { specialization_of_template_helper(std::forward(x)) } -> std::same_as; + ^ +../../../include/cpp2util.h:1813:16: note: candidate function template not viable: requires 0 arguments, but 1 was provided +constexpr auto as() -> auto + ^ +../../../include/cpp2util.h:1824:16: note: candidate function template not viable: requires 0 arguments, but 1 was provided +constexpr auto as() -> auto + ^ +../../../include/cpp2util.h:2905:9: error: static assertion failed due to requirement 'program_violates_type_safety_guarantee': No safe 'as' cast available - please check your cast + static_assert( + ^ +../../../include/cpp2util.h:2911:12: error: no matching function for call to 'as' + return as(CPP2_FORWARD(x)); + ^~~~~ +../../../include/cpp2util.h:1838:16: note: candidate template ignored: constraints not satisfied [with C = int, x:auto = double (&)(double) noexcept] +constexpr auto as(auto&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto) + ^ +../../../include/cpp2util.h:1844:18: note: because 'std::is_scalar_v >' evaluated to false + (std::is_scalar_v && !std::is_enum_v) + ^ +../../../include/cpp2util.h:1845:17: note: and 'std::is_floating_point_v >' evaluated to false + || std::is_floating_point_v + ^ +../../../include/cpp2util.h:1846:17: note: and 'std::is_base_of_v >' evaluated to false + || std::is_base_of_v + ^ +../../../include/cpp2util.h:1847:17: note: and 'std::is_base_of_v, int>' evaluated to false + || std::is_base_of_v + ^ +../../../include/cpp2util.h:1848:30: note: and 'C{std::forward(x)}' would be invalid: cannot initialize a value of type 'int' with an lvalue of type 'double (double) noexcept' + || requires { C{CPP2_FORWARD(x)}; } + ^ +../../../include/cpp2util.h:325:37: note: expanded from macro 'CPP2_FORWARD' +#define CPP2_FORWARD(x) std::forward(x) + ^ +../../../include/cpp2util.h:1977:6: note: candidate template ignored: constraints not satisfied [with C = int, X = double (&)(double) noexcept] +auto as(X&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto) + ^ +../../../include/cpp2util.h:1976:23: note: because 'specialization_of_template' evaluated to false +template< typename C, specialization_of_template X > + ^ +../../../include/cpp2util.h:724:7: note: because 'specialization_of_template_helper(std::forward(x))' would be invalid: no matching function for call to 'specialization_of_template_helper' + { specialization_of_template_helper(std::forward(x)) } -> std::same_as; + ^ +../../../include/cpp2util.h:2024:16: note: candidate template ignored: constraints not satisfied [with T = int, X = double (&)(double) noexcept] +constexpr auto as( X && x ) -> decltype(auto) { + ^ +../../../include/cpp2util.h:2023:22: note: because 'same_type_as' evaluated to false +template X> + ^ +../../../include/cpp2util.h:754:24: note: because 'std::same_as, std::remove_cvref_t >' evaluated to false +concept same_type_as = std::same_as, std::remove_cvref_t>; + ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/concepts:63:9: note: because '__detail::__same_as' evaluated to false + = __detail::__same_as<_Tp, _Up> && __detail::__same_as<_Up, _Tp>; + ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/concepts:57:27: note: because 'std::is_same_v' evaluated to false + concept __same_as = std::is_same_v<_Tp, _Up>; + ^ +../../../include/cpp2util.h:2069:16: note: candidate template ignored: constraints not satisfied [with T = int, X = double (&)(double) noexcept] +constexpr auto as( X&& x ) -> decltype(auto) { + ^ +../../../include/cpp2util.h:2068:22: note: because 'specialization_of_template' evaluated to false +template X> + ^ +../../../include/cpp2util.h:724:7: note: because 'specialization_of_template_helper(std::forward(x))' would be invalid: no matching function for call to 'specialization_of_template_helper' + { specialization_of_template_helper(std::forward(x)) } -> std::same_as; + ^ +../../../include/cpp2util.h:1813:16: note: candidate function template not viable: requires 0 arguments, but 1 was provided +constexpr auto as() -> auto + ^ +../../../include/cpp2util.h:1824:16: note: candidate function template not viable: requires 0 arguments, but 1 was provided +constexpr auto as() -> auto + ^ +pure2-expected-is-as.cpp2:39:37: error: use of undeclared identifier 'ex1' + auto val1 {cpp2::impl::as_(ex1)}; + ^ +fatal error: too many errors emitted, stopping now [-ferror-limit=] +1 warning and 20 errors generated. diff --git a/regression-tests/test-results/clang-18-c++20/pure2-expected-is-as.cpp.output b/regression-tests/test-results/clang-18-c++20/pure2-expected-is-as.cpp.output new file mode 100644 index 000000000..5c06a61b0 --- /dev/null +++ b/regression-tests/test-results/clang-18-c++20/pure2-expected-is-as.cpp.output @@ -0,0 +1,245 @@ +pure2-expected-is-as.cpp2:7:22: error: expected '(' for function-style cast or type construction + 7 | std::expected ex1 {123}; + | ~~~^ +pure2-expected-is-as.cpp2:7:10: error: no member named 'expected' in namespace 'std'; did you mean 'unexpected'? + 7 | std::expected ex1 {123}; + | ~~~~~^~~~~~~~ + | unexpected +/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/exception:110:8: note: 'unexpected' declared here + 110 | void unexpected() __attribute__ ((__noreturn__,__cold__)); + | ^ +pure2-expected-is-as.cpp2:8:22: error: expected '(' for function-style cast or type construction + 8 | std::expected ex2 {std::unexpected(-1)}; + | ~~~^ +pure2-expected-is-as.cpp2:8:10: error: no member named 'expected' in namespace 'std'; did you mean 'unexpected'? + 8 | std::expected ex2 {std::unexpected(-1)}; + | ~~~~~^~~~~~~~ + | unexpected +/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/exception:110:8: note: 'unexpected' declared here + 110 | void unexpected() __attribute__ ((__noreturn__,__cold__)); + | ^ +pure2-expected-is-as.cpp2:9:30: error: expected '(' for function-style cast or type construction + 9 | std::expected ex3 {"Expect the unexpected"}; + | ~~~~~~~~~~~^ +pure2-expected-is-as.cpp2:9:10: error: no member named 'expected' in namespace 'std'; did you mean 'unexpected'? + 9 | std::expected ex3 {"Expect the unexpected"}; + | ~~~~~^~~~~~~~ + | unexpected +/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/exception:110:8: note: 'unexpected' declared here + 110 | void unexpected() __attribute__ ((__noreturn__,__cold__)); + | ^ +pure2-expected-is-as.cpp2:11:29: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + 11 | if (cpp2::impl::is(ex1)) { + | ^~~ + | exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here + 95 | __MATHCALL_VEC (exp,, (_Mdouble_ __x)); + | ^ +pure2-expected-is-as.cpp2:15:30: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + 15 | if (cpp2::impl::is(ex1)) { + | ^~~ + | exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here + 95 | __MATHCALL_VEC (exp,, (_Mdouble_ __x)); + | ^ +pure2-expected-is-as.cpp2:20:30: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + 20 | if (cpp2::impl::is(ex1)) { + | ^~~ + | exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here + 95 | __MATHCALL_VEC (exp,, (_Mdouble_ __x)); + | ^ +pure2-expected-is-as.cpp2:25:29: warning: 'unexpected' is deprecated [-Wdeprecated-declarations] + 25 | if (cpp2::impl::is>(ex1)) { + | ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/exception:109:3: note: 'unexpected' has been explicitly marked deprecated here + 109 | _GLIBCXX11_DEPRECATED + | ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14/bits/c++config.h:107:32: note: expanded from macro '_GLIBCXX11_DEPRECATED' + 107 | # define _GLIBCXX11_DEPRECATED _GLIBCXX_DEPRECATED + | ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14/bits/c++config.h:98:46: note: expanded from macro '_GLIBCXX_DEPRECATED' + 98 | # define _GLIBCXX_DEPRECATED __attribute__ ((__deprecated__)) + | ^ +pure2-expected-is-as.cpp2:25:29: error: 'unexpected' does not name a template but is followed by template arguments + 25 | if (cpp2::impl::is>(ex1)) { + | ^ ~~~~~ +/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/exception:110:8: note: non-template declaration found by name lookup + 110 | void unexpected() __attribute__ ((__noreturn__,__cold__)); + | ^ +pure2-expected-is-as.cpp2:25:46: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + 25 | if (cpp2::impl::is>(ex1)) { + | ^~~ + | exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here + 95 | __MATHCALL_VEC (exp,, (_Mdouble_ __x)); + | ^ +pure2-expected-is-as.cpp2:30:24: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + 30 | if (cpp2::impl::is(ex1, 123)) { + | ^~~ + | exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here + 95 | __MATHCALL_VEC (exp,, (_Mdouble_ __x)); + | ^ +pure2-expected-is-as.cpp2:34:24: error: use of undeclared identifier 'ex1'; did you mean 'exp'? + 34 | if (cpp2::impl::is(ex1, 100)) { + | ^~~ + | exp +/usr/include/x86_64-linux-gnu/bits/mathcalls.h:95:17: note: 'exp' declared here + 95 | __MATHCALL_VEC (exp,, (_Mdouble_ __x)); + | ^ +In file included from pure2-expected-is-as.cpp:7: +../../../include/cpp2util.h:1770:72: error: invalid application of 'sizeof' to a function type + 1770 | (std::is_floating_point_v && std::is_floating_point_v && sizeof(From) > sizeof(To)) || // NOLINT(misc-redundant-expression) + | ^~~~~~~~~~~~ +../../../include/cpp2util.h:2891:19: note: in instantiation of variable template specialization 'cpp2::impl::is_narrowing_v' requested here + 2891 | if constexpr (is_narrowing_v) { + | ^ +pure2-expected-is-as.cpp2:39:28: note: in instantiation of function template specialization 'cpp2::impl::as_' requested here + 39 | auto val1 {cpp2::impl::as_(ex1)}; + | ^ +In file included from pure2-expected-is-as.cpp:7: +../../../include/cpp2util.h:2893:13: error: static assertion failed due to requirement 'program_violates_type_safety_guarantee': 'as' does not allow unsafe possibly-lossy narrowing conversions - if you're sure you want this, use 'unchecked_narrow' to explicitly force the conversion and possibly lose information + 2893 | program_violates_type_safety_guarantee, + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pure2-expected-is-as.cpp2:39:28: note: in instantiation of function template specialization 'cpp2::impl::as_' requested here + 39 | auto val1 {cpp2::impl::as_(ex1)}; + | ^ +In file included from pure2-expected-is-as.cpp:7: +../../../include/cpp2util.h:2904:52: error: no matching function for call to 'as' + 2904 | else if constexpr( std::is_same_v< CPP2_TYPEOF(as(CPP2_FORWARD(x))), nonesuch_ > ) { + | ^~~~~ +../../../include/cpp2util.h:315:66: note: expanded from macro 'CPP2_TYPEOF' + 315 | #define CPP2_TYPEOF(x) std::remove_cvref_t + | ^ +../../../include/cpp2util.h:1838:16: note: candidate template ignored: constraints not satisfied [with C = int, x:auto = double (&)(double) noexcept] + 1838 | constexpr auto as(auto&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto) + | ^ +../../../include/cpp2util.h:1844:18: note: because 'std::is_scalar_v >' evaluated to false + 1844 | (std::is_scalar_v && !std::is_enum_v) + | ^ +../../../include/cpp2util.h:1845:17: note: and 'std::is_floating_point_v >' evaluated to false + 1845 | || std::is_floating_point_v + | ^ +../../../include/cpp2util.h:1846:17: note: and 'std::is_base_of_v >' evaluated to false + 1846 | || std::is_base_of_v + | ^ +../../../include/cpp2util.h:1847:17: note: and 'std::is_base_of_v, int>' evaluated to false + 1847 | || std::is_base_of_v + | ^ +../../../include/cpp2util.h:1848:30: note: and 'C{std::forward(x)}' would be invalid: cannot initialize a value of type 'int' with an lvalue of type 'double (double) noexcept' + 1848 | || requires { C{CPP2_FORWARD(x)}; } + | ^ +../../../include/cpp2util.h:325:37: note: expanded from macro 'CPP2_FORWARD' + 325 | #define CPP2_FORWARD(x) std::forward(x) + | ^ +../../../include/cpp2util.h:1977:6: note: candidate template ignored: constraints not satisfied [with C = int, X = double (&)(double) noexcept] + 1977 | auto as(X&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto) + | ^ +../../../include/cpp2util.h:1976:23: note: because 'specialization_of_template' evaluated to false + 1976 | template< typename C, specialization_of_template X > + | ^ +../../../include/cpp2util.h:724:7: note: because 'specialization_of_template_helper(std::forward(x))' would be invalid: no matching function for call to 'specialization_of_template_helper' + 724 | { specialization_of_template_helper(std::forward(x)) } -> std::same_as; + | ^ +../../../include/cpp2util.h:2024:16: note: candidate template ignored: constraints not satisfied [with T = int, X = double (&)(double) noexcept] + 2024 | constexpr auto as( X && x ) -> decltype(auto) { + | ^ +../../../include/cpp2util.h:2023:22: note: because 'same_type_as' evaluated to false + 2023 | template X> + | ^ +../../../include/cpp2util.h:754:24: note: because 'std::same_as, std::remove_cvref_t >' evaluated to false + 754 | concept same_type_as = std::same_as, std::remove_cvref_t>; + | ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/concepts:63:9: note: because '__detail::__same_as' evaluated to false + 63 | = __detail::__same_as<_Tp, _Up> && __detail::__same_as<_Up, _Tp>; + | ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/concepts:57:27: note: because 'std::is_same_v' evaluated to false + 57 | concept __same_as = std::is_same_v<_Tp, _Up>; + | ^ +../../../include/cpp2util.h:2069:16: note: candidate template ignored: constraints not satisfied [with T = int, X = double (&)(double) noexcept] + 2069 | constexpr auto as( X&& x ) -> decltype(auto) { + | ^ +../../../include/cpp2util.h:2068:22: note: because 'specialization_of_template' evaluated to false + 2068 | template X> + | ^ +../../../include/cpp2util.h:724:7: note: because 'specialization_of_template_helper(std::forward(x))' would be invalid: no matching function for call to 'specialization_of_template_helper' + 724 | { specialization_of_template_helper(std::forward(x)) } -> std::same_as; + | ^ +../../../include/cpp2util.h:1813:16: note: candidate function template not viable: requires 0 arguments, but 1 was provided + 1813 | constexpr auto as() -> auto + | ^ +../../../include/cpp2util.h:1824:16: note: candidate function template not viable: requires 0 arguments, but 1 was provided + 1824 | constexpr auto as() -> auto + | ^ +../../../include/cpp2util.h:2906:13: error: static assertion failed due to requirement 'program_violates_type_safety_guarantee': No safe 'as' cast available - please check your cast + 2906 | program_violates_type_safety_guarantee, + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +../../../include/cpp2util.h:2911:12: error: no matching function for call to 'as' + 2911 | return as(CPP2_FORWARD(x)); + | ^~~~~ +../../../include/cpp2util.h:1838:16: note: candidate template ignored: constraints not satisfied [with C = int, x:auto = double (&)(double) noexcept] + 1838 | constexpr auto as(auto&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto) + | ^ +../../../include/cpp2util.h:1844:18: note: because 'std::is_scalar_v >' evaluated to false + 1844 | (std::is_scalar_v && !std::is_enum_v) + | ^ +../../../include/cpp2util.h:1845:17: note: and 'std::is_floating_point_v >' evaluated to false + 1845 | || std::is_floating_point_v + | ^ +../../../include/cpp2util.h:1846:17: note: and 'std::is_base_of_v >' evaluated to false + 1846 | || std::is_base_of_v + | ^ +../../../include/cpp2util.h:1847:17: note: and 'std::is_base_of_v, int>' evaluated to false + 1847 | || std::is_base_of_v + | ^ +../../../include/cpp2util.h:1848:30: note: and 'C{std::forward(x)}' would be invalid: cannot initialize a value of type 'int' with an lvalue of type 'double (double) noexcept' + 1848 | || requires { C{CPP2_FORWARD(x)}; } + | ^ +../../../include/cpp2util.h:325:37: note: expanded from macro 'CPP2_FORWARD' + 325 | #define CPP2_FORWARD(x) std::forward(x) + | ^ +../../../include/cpp2util.h:1977:6: note: candidate template ignored: constraints not satisfied [with C = int, X = double (&)(double) noexcept] + 1977 | auto as(X&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto) + | ^ +../../../include/cpp2util.h:1976:23: note: because 'specialization_of_template' evaluated to false + 1976 | template< typename C, specialization_of_template X > + | ^ +../../../include/cpp2util.h:724:7: note: because 'specialization_of_template_helper(std::forward(x))' would be invalid: no matching function for call to 'specialization_of_template_helper' + 724 | { specialization_of_template_helper(std::forward(x)) } -> std::same_as; + | ^ +../../../include/cpp2util.h:2024:16: note: candidate template ignored: constraints not satisfied [with T = int, X = double (&)(double) noexcept] + 2024 | constexpr auto as( X && x ) -> decltype(auto) { + | ^ +../../../include/cpp2util.h:2023:22: note: because 'same_type_as' evaluated to false + 2023 | template X> + | ^ +../../../include/cpp2util.h:754:24: note: because 'std::same_as, std::remove_cvref_t >' evaluated to false + 754 | concept same_type_as = std::same_as, std::remove_cvref_t>; + | ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/concepts:63:9: note: because '__detail::__same_as' evaluated to false + 63 | = __detail::__same_as<_Tp, _Up> && __detail::__same_as<_Up, _Tp>; + | ^ +/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/concepts:57:27: note: because 'std::is_same_v' evaluated to false + 57 | concept __same_as = std::is_same_v<_Tp, _Up>; + | ^ +../../../include/cpp2util.h:2069:16: note: candidate template ignored: constraints not satisfied [with T = int, X = double (&)(double) noexcept] + 2069 | constexpr auto as( X&& x ) -> decltype(auto) { + | ^ +../../../include/cpp2util.h:2068:22: note: because 'specialization_of_template' evaluated to false + 2068 | template X> + | ^ +../../../include/cpp2util.h:724:7: note: because 'specialization_of_template_helper(std::forward(x))' would be invalid: no matching function for call to 'specialization_of_template_helper' + 724 | { specialization_of_template_helper(std::forward(x)) } -> std::same_as; + | ^ +../../../include/cpp2util.h:1813:16: note: candidate function template not viable: requires 0 arguments, but 1 was provided + 1813 | constexpr auto as() -> auto + | ^ +../../../include/cpp2util.h:1824:16: note: candidate function template not viable: requires 0 arguments, but 1 was provided + 1824 | constexpr auto as() -> auto + | ^ +pure2-expected-is-as.cpp2:39:37: error: use of undeclared identifier 'ex1' + 39 | auto val1 {cpp2::impl::as_(ex1)}; + | ^ +fatal error: too many errors emitted, stopping now [-ferror-limit=] +1 warning and 20 errors generated. diff --git a/regression-tests/test-results/clang-18-c++23-libcpp/pure2-expected-is-as.cpp.execution b/regression-tests/test-results/clang-18-c++23-libcpp/pure2-expected-is-as.cpp.execution new file mode 100644 index 000000000..5483d6cd7 --- /dev/null +++ b/regression-tests/test-results/clang-18-c++23-libcpp/pure2-expected-is-as.cpp.execution @@ -0,0 +1,15 @@ +ex1 is int +ex1 is 123 +ex1 as int = 123 +ex2 is unexpected and error is: -1 +ex2 is 'empty' aka unexpected and error is: -1 +ex2 as std::unexpected and error = -1 + +expected with value + ...integer 123 + +expected with unexpected + ...unexpected -1 + +expected with value + ...string Expect the unexpected diff --git a/regression-tests/test-results/gcc-10-c++20/pure2-expected-is-as.cpp.output b/regression-tests/test-results/gcc-10-c++20/pure2-expected-is-as.cpp.output new file mode 100644 index 000000000..bce72f964 --- /dev/null +++ b/regression-tests/test-results/gcc-10-c++20/pure2-expected-is-as.cpp.output @@ -0,0 +1,39 @@ +pure2-expected-is-as.cpp2: In function ‘int main()’: +pure2-expected-is-as.cpp2:7:10: error: ‘expected’ is not a member of ‘std’; did you mean ‘unexpected’? +pure2-expected-is-as.cpp2:7:19: error: expected primary-expression before ‘int’ +pure2-expected-is-as.cpp2:8:10: error: ‘expected’ is not a member of ‘std’; did you mean ‘unexpected’? +pure2-expected-is-as.cpp2:8:19: error: expected primary-expression before ‘int’ +pure2-expected-is-as.cpp2:9:10: error: ‘expected’ is not a member of ‘std’; did you mean ‘unexpected’? +pure2-expected-is-as.cpp2:9:30: error: expected primary-expression before ‘,’ token +pure2-expected-is-as.cpp2:9:37: error: expected primary-expression before ‘>’ token +pure2-expected-is-as.cpp2:9:39: error: ‘ex3’ was not declared in this scope; did you mean ‘exp’? +pure2-expected-is-as.cpp2:11:29: error: ‘ex1’ was not declared in this scope; did you mean ‘exp’? +pure2-expected-is-as.cpp2:15:30: error: ‘ex1’ was not declared in this scope; did you mean ‘exp’? +pure2-expected-is-as.cpp2:20:30: error: ‘ex1’ was not declared in this scope; did you mean ‘exp’? +pure2-expected-is-as.cpp2:25:21: error: parse error in template argument list +pure2-expected-is-as.cpp2:25:46: error: ‘ex1’ was not declared in this scope; did you mean ‘exp’? +pure2-expected-is-as.cpp2:30:24: error: ‘ex1’ was not declared in this scope; did you mean ‘exp’? +pure2-expected-is-as.cpp2:34:24: error: ‘ex1’ was not declared in this scope; did you mean ‘exp’? +pure2-expected-is-as.cpp2:39:37: error: ‘ex1’ was not declared in this scope; did you mean ‘exp’? +pure2-expected-is-as.cpp2:42:29: error: ‘ex2’ was not declared in this scope; did you mean ‘exp2’? +pure2-expected-is-as.cpp2:47:30: error: ‘ex2’ was not declared in this scope; did you mean ‘exp2’? +pure2-expected-is-as.cpp2:52:24: error: ‘ex2’ was not declared in this scope; did you mean ‘exp2’? +pure2-expected-is-as.cpp2:57:21: error: parse error in template argument list +pure2-expected-is-as.cpp2:57:46: error: ‘ex2’ was not declared in this scope; did you mean ‘exp2’? +pure2-expected-is-as.cpp2:61:30: error: ‘ex2’ was not declared in this scope; did you mean ‘exp2’? +pure2-expected-is-as.cpp2:65:31: error: parse error in template argument list +pure2-expected-is-as.cpp2:65:57: error: ‘ex2’ was not declared in this scope; did you mean ‘exp2’? +pure2-expected-is-as.cpp2: In function ‘void test_inspect(const auto:110&, const auto:111&)’: +pure2-expected-is-as.cpp2:77:55: error: template argument 1 is invalid +pure2-expected-is-as.cpp2:77:21: error: ‘cpp2::impl::unexp’ has not been declared +pure2-expected-is-as.cpp2: In lambda function: +pure2-expected-is-as.cpp2:78:33: error: ‘unexp’ was not declared in this scope +pure2-expected-is-as.cpp2: In lambda function: +pure2-expected-is-as.cpp2:85:34: error: parse error in template argument list +pure2-expected-is-as.cpp2:85:159: error: parse error in template argument list +In file included from pure2-expected-is-as.cpp:7: +pure2-expected-is-as.cpp2:85:309: error: parse error in template argument list +../../../include/cpp2util.h:315:66: note: in definition of macro ‘CPP2_TYPEOF’ + 315 | #define CPP2_TYPEOF(x) std::remove_cvref_t + | ^ +pure2-expected-is-as.cpp2:85:430: error: parse error in template argument list diff --git a/regression-tests/test-results/gcc-13-c++2b/pure2-expected-is-as.cpp.execution b/regression-tests/test-results/gcc-13-c++2b/pure2-expected-is-as.cpp.execution new file mode 100644 index 000000000..5483d6cd7 --- /dev/null +++ b/regression-tests/test-results/gcc-13-c++2b/pure2-expected-is-as.cpp.execution @@ -0,0 +1,15 @@ +ex1 is int +ex1 is 123 +ex1 as int = 123 +ex2 is unexpected and error is: -1 +ex2 is 'empty' aka unexpected and error is: -1 +ex2 as std::unexpected and error = -1 + +expected with value + ...integer 123 + +expected with unexpected + ...unexpected -1 + +expected with value + ...string Expect the unexpected diff --git a/regression-tests/test-results/gcc-14-c++2b/pure2-expected-is-as.cpp.execution b/regression-tests/test-results/gcc-14-c++2b/pure2-expected-is-as.cpp.execution new file mode 100644 index 000000000..5483d6cd7 --- /dev/null +++ b/regression-tests/test-results/gcc-14-c++2b/pure2-expected-is-as.cpp.execution @@ -0,0 +1,15 @@ +ex1 is int +ex1 is 123 +ex1 as int = 123 +ex2 is unexpected and error is: -1 +ex2 is 'empty' aka unexpected and error is: -1 +ex2 as std::unexpected and error = -1 + +expected with value + ...integer 123 + +expected with unexpected + ...unexpected -1 + +expected with value + ...string Expect the unexpected diff --git a/regression-tests/test-results/msvc-2022-c++20/pure2-expected-is-as.cpp.output b/regression-tests/test-results/msvc-2022-c++20/pure2-expected-is-as.cpp.output new file mode 100644 index 000000000..9b87b96a3 --- /dev/null +++ b/regression-tests/test-results/msvc-2022-c++20/pure2-expected-is-as.cpp.output @@ -0,0 +1,67 @@ +pure2-expected-is-as.cpp +pure2-expected-is-as.cpp2(7): error C2039: 'expected': is not a member of 'std' +predefined C++ types (compiler internal)(347): note: see declaration of 'std' +pure2-expected-is-as.cpp2(7): error C2062: type 'int' unexpected +pure2-expected-is-as.cpp2(7): error C2143: syntax error: missing ';' before '{' +pure2-expected-is-as.cpp2(7): error C2143: syntax error: missing ';' before '}' +pure2-expected-is-as.cpp2(8): error C2039: 'expected': is not a member of 'std' +predefined C++ types (compiler internal)(347): note: see declaration of 'std' +pure2-expected-is-as.cpp2(8): error C2062: type 'int' unexpected +pure2-expected-is-as.cpp2(8): error C2143: syntax error: missing ';' before '{' +pure2-expected-is-as.cpp2(8): error C2039: 'unexpected': is not a member of 'std' +predefined C++ types (compiler internal)(347): note: see declaration of 'std' +pure2-expected-is-as.cpp2(8): error C2660: 'unexpected': function does not take 1 arguments +C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.41.34120\include\eh.h(33): note: see declaration of 'unexpected' +pure2-expected-is-as.cpp2(8): note: while trying to match the argument list '(int)' +pure2-expected-is-as.cpp2(8): error C2143: syntax error: missing ';' before '}' +pure2-expected-is-as.cpp2(9): error C2039: 'expected': is not a member of 'std' +predefined C++ types (compiler internal)(347): note: see declaration of 'std' +pure2-expected-is-as.cpp2(9): error C2275: 'std::string': expected an expression instead of a type +pure2-expected-is-as.cpp2(9): error C2065: 'ex3': undeclared identifier +pure2-expected-is-as.cpp2(9): error C2275: 'size_t': expected an expression instead of a type +pure2-expected-is-as.cpp2(11): error C2065: 'ex1': undeclared identifier +pure2-expected-is-as.cpp2(15): error C2065: 'ex1': undeclared identifier +pure2-expected-is-as.cpp2(20): error C2065: 'ex1': undeclared identifier +pure2-expected-is-as.cpp2(25): error C2039: 'unexpected': is not a member of 'std' +predefined C++ types (compiler internal)(347): note: see declaration of 'std' +pure2-expected-is-as.cpp2(25): error C2062: type 'int' unexpected +pure2-expected-is-as.cpp2(25): error C2059: syntax error: '>' +pure2-expected-is-as.cpp2(25): error C2143: syntax error: missing ';' before '{' +pure2-expected-is-as.cpp2(30): error C2065: 'ex1': undeclared identifier +pure2-expected-is-as.cpp2(34): error C2065: 'ex1': undeclared identifier +pure2-expected-is-as.cpp2(39): error C2065: 'ex1': undeclared identifier +pure2-expected-is-as.cpp2(39): error C2119: 'val1': the type for 'auto' cannot be deduced from an empty initializer +pure2-expected-is-as.cpp2(42): error C2065: 'ex2': undeclared identifier +pure2-expected-is-as.cpp2(47): error C2065: 'ex2': undeclared identifier +pure2-expected-is-as.cpp2(52): error C2065: 'ex2': undeclared identifier +pure2-expected-is-as.cpp2(57): error C2039: 'unexpected': is not a member of 'std' +predefined C++ types (compiler internal)(347): note: see declaration of 'std' +pure2-expected-is-as.cpp2(57): error C2062: type 'int' unexpected +pure2-expected-is-as.cpp2(57): error C2059: syntax error: '>' +pure2-expected-is-as.cpp2(57): error C2143: syntax error: missing ';' before '{' +pure2-expected-is-as.cpp2(58): error C2065: 'ex2': undeclared identifier +pure2-expected-is-as.cpp2(61): error C2065: 'ex2': undeclared identifier +pure2-expected-is-as.cpp2(62): error C2065: 'ex2': undeclared identifier +pure2-expected-is-as.cpp2(65): error C2039: 'unexpected': is not a member of 'std' +predefined C++ types (compiler internal)(347): note: see declaration of 'std' +pure2-expected-is-as.cpp2(65): error C2062: type 'int' unexpected +pure2-expected-is-as.cpp2(65): error C2062: type 'unknown-type' unexpected +pure2-expected-is-as.cpp2(65): error C2143: syntax error: missing ';' before '}' +pure2-expected-is-as.cpp2(66): error C2143: syntax error: missing ';' before '<<' +pure2-expected-is-as.cpp2(66): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int +pure2-expected-is-as.cpp2(66): error C2371: 'std::cout': redefinition; different basic types +C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.41.34120\include\iostream(39): note: see declaration of 'std::cout' +pure2-expected-is-as.cpp2(66): error C2059: syntax error: '<<' +pure2-expected-is-as.cpp2(66): error C2143: syntax error: missing ';' before '{' +pure2-expected-is-as.cpp2(66): error C2447: '{': missing function header (old-style formal list?) +pure2-expected-is-as.cpp2(66): error C2059: syntax error: '||' +pure2-expected-is-as.cpp2(66): error C2065: 'Obj': undeclared identifier +pure2-expected-is-as.cpp2(66): error C2065: 'Params': undeclared identifier +pure2-expected-is-as.cpp2(66): error C2059: syntax error: '}' +pure2-expected-is-as.cpp2(66): error C2143: syntax error: missing ')' before ';' +pure2-expected-is-as.cpp2(66): error C2059: syntax error: 'requires' +pure2-expected-is-as.cpp2(66): error C2059: syntax error: ')' +pure2-expected-is-as.cpp2(66): error C2065: 'obj': undeclared identifier +pure2-expected-is-as.cpp2(66): error C3553: decltype expects an expression not a type +pure2-expected-is-as.cpp2(66): error C2065: 'params': undeclared identifier +pure2-expected-is-as.cpp2(66): fatal error C1003: error count exceeds 100; stopping compilation diff --git a/regression-tests/test-results/msvc-2022-c++latest/pure2-expected-is-as.cpp.execution b/regression-tests/test-results/msvc-2022-c++latest/pure2-expected-is-as.cpp.execution new file mode 100644 index 000000000..5483d6cd7 --- /dev/null +++ b/regression-tests/test-results/msvc-2022-c++latest/pure2-expected-is-as.cpp.execution @@ -0,0 +1,15 @@ +ex1 is int +ex1 is 123 +ex1 as int = 123 +ex2 is unexpected and error is: -1 +ex2 is 'empty' aka unexpected and error is: -1 +ex2 as std::unexpected and error = -1 + +expected with value + ...integer 123 + +expected with unexpected + ...unexpected -1 + +expected with value + ...string Expect the unexpected diff --git a/regression-tests/test-results/msvc-2022-c++latest/pure2-expected-is-as.cpp.output b/regression-tests/test-results/msvc-2022-c++latest/pure2-expected-is-as.cpp.output new file mode 100644 index 000000000..6e7839bd6 --- /dev/null +++ b/regression-tests/test-results/msvc-2022-c++latest/pure2-expected-is-as.cpp.output @@ -0,0 +1 @@ +pure2-expected-is-as.cpp diff --git a/regression-tests/test-results/pure2-expected-is-as.cpp b/regression-tests/test-results/pure2-expected-is-as.cpp new file mode 100644 index 000000000..956d9547e --- /dev/null +++ b/regression-tests/test-results/pure2-expected-is-as.cpp @@ -0,0 +1,117 @@ + +#define CPP2_IMPORT_STD Yes + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "pure2-expected-is-as.cpp2" + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "pure2-expected-is-as.cpp2" +// `std::expected` requires C++23 so a dedicated test file is needed +// since only MSVC supports it at time of writing, and there's no #ifdef +// or `static if` support in Cpp2 (yet?). + +#line 5 "pure2-expected-is-as.cpp2" +[[nodiscard]] auto main() -> int; + +#line 75 "pure2-expected-is-as.cpp2" +auto test_inspect(auto const& x, auto const& msg) -> void; + +//=== Cpp2 function definitions ================================================= + +#line 1 "pure2-expected-is-as.cpp2" + +#line 5 "pure2-expected-is-as.cpp2" +[[nodiscard]] auto main() -> int{ + + std::expected ex1 {123}; + std::expected ex2 {std::unexpected(-1)}; + std::expected ex3 {"Expect the unexpected"}; + + if (cpp2::impl::is(ex1)) { + std::cout << "ex1 is int\n"; + } + + if (cpp2::impl::is(ex1)) { + std::cout << "BUG - ex1 is not a bool\n"; + return -1; + } + + if (cpp2::impl::is(ex1)) { + std::cout << "BUG - ex1 is not 'empty'\n"; + return -1; + } + + if (cpp2::impl::is>(ex1)) { + std::cout << "BUG - ex1 is not unexpected\n"; + return -1; + } + + if (cpp2::impl::is(ex1, 123)) { + std::cout << "ex1 is 123\n"; + } + + if (cpp2::impl::is(ex1, 100)) { + std::cout << "BUG - ex1's value is not 100\n"; + return -1; + } + + auto val1 {cpp2::impl::as_(ex1)}; + std::cout << "ex1 as int = " << cpp2::move(val1) << "\n"; + + if (cpp2::impl::is(ex2)) { + std::cout << "BUG - ex2 is not an int\n"; + return -1; + } + + if (cpp2::impl::is(ex2)) { + std::cout << "BUG - ex2 is not a bool\n"; + return -1; + } + + if (cpp2::impl::is(ex2, 123)) { + std::cout << "BUG - ex2 does not have a value\n"; + return -1; + } + + if (cpp2::impl::is>(ex2)) { + std::cout << "ex2 is unexpected and error is: " << CPP2_UFCS(error)(ex2) << "\n"; + } + + if (cpp2::impl::is(ex2)) { + std::cout << "ex2 is 'empty' aka unexpected and error is: " << CPP2_UFCS(error)(ex2) << "\n"; + } + + auto ex2_err {cpp2::impl::as_>(ex2)}; + std::cout << "ex2 as std::unexpected and error = " << CPP2_UFCS(error)(cpp2::move(ex2_err)) << "\n"; + + test_inspect(cpp2::move(ex1), "expected with value"); + test_inspect(cpp2::move(ex2), "expected with unexpected"); + test_inspect(cpp2::move(ex3), "expected with value"); + + return 0; +} + +#line 75 "pure2-expected-is-as.cpp2" +auto test_inspect(auto const& x, auto const& msg) -> void{ + + auto unwrap {[](cpp2::impl::in> unexp) -> auto{ + return CPP2_UFCS(error)(unexp); + }}; + + std::cout + << "\n" << msg << "\n ..." + << [&] () -> std::string { auto&& _expr = x; + if (cpp2::impl::is(_expr)) { if constexpr( requires{"integer " + std::to_string(cpp2::impl::as(x));} ) if constexpr( std::is_convertible_v(x)))),std::string> ) return "integer " + std::to_string(cpp2::impl::as(x)); else return std::string{}; else return std::string{}; } + else if (cpp2::impl::is>(_expr)) { if constexpr( requires{"unexpected " + std::to_string(cpp2::move(unwrap)(cpp2::impl::as>(x)));} ) if constexpr( std::is_convertible_v " + std::to_string(cpp2::move(unwrap)(cpp2::impl::as>(x))))),std::string> ) return "unexpected " + std::to_string(cpp2::move(unwrap)(cpp2::impl::as>(x))); else return std::string{}; else return std::string{}; } + else if (cpp2::impl::is(_expr)) { if constexpr( requires{"string " + cpp2::impl::as(x);} ) if constexpr( std::is_convertible_v(x))),std::string> ) return "string " + cpp2::impl::as(x); else return std::string{}; else return std::string{}; } + else return " no match"; } + () + << "\n"; +} + diff --git a/regression-tests/test-results/pure2-expected-is-as.cpp2.output b/regression-tests/test-results/pure2-expected-is-as.cpp2.output new file mode 100644 index 000000000..a63d2c2a1 --- /dev/null +++ b/regression-tests/test-results/pure2-expected-is-as.cpp2.output @@ -0,0 +1,2 @@ +pure2-expected-is-as.cpp2... ok (all Cpp2, passes safety checks) +