diff --git a/test/Jamfile b/test/Jamfile index 39c9aaf..a451e8a 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -36,3 +36,8 @@ run invoke_md_test.cpp ; run mem_fn_mfn_test.cpp ; run mem_fn_md_test.cpp ; + +run invoke_fn_noexcept_test.cpp ; +run invoke_obj_noexcept_test.cpp ; +run invoke_mfn_noexcept_test.cpp ; +run invoke_md_noexcept_test.cpp ; diff --git a/test/invoke_fn_noexcept_test.cpp b/test/invoke_fn_noexcept_test.cpp new file mode 100644 index 0000000..7b5efa4 --- /dev/null +++ b/test/invoke_fn_noexcept_test.cpp @@ -0,0 +1,47 @@ +// Copyright 2024 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#if !defined(__cpp_noexcept_function_type) + +BOOST_PRAGMA_MESSAGE( "Test skipped, __cpp_noexcept_function_type is not defined" ) +int main() {} + +#else + +#include +#include + +int f0() +{ + return -1; +} + +int f1( int x1 ) noexcept +{ + return x1; +} + +int f2( int x1, int x2 ) +{ + return 10*x1+x2; +} + +int f3( int x1, int x2, int x3 ) noexcept +{ + return 100*x1 + 10*x2 + x3; +} + +int main() +{ + BOOST_TEST_EQ( noexcept( boost::compat::invoke( f0 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( f1, 1 ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( f2, 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( f3, 1, 2, 3 ) ), true ); + + return boost::report_errors(); +} + +#endif diff --git a/test/invoke_md_noexcept_test.cpp b/test/invoke_md_noexcept_test.cpp new file mode 100644 index 0000000..841317b --- /dev/null +++ b/test/invoke_md_noexcept_test.cpp @@ -0,0 +1,60 @@ +// Copyright 2024 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +struct X +{ + int m = -1; +}; + +struct Y: public virtual X +{ +}; + +int main() +{ + { + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, X() ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, Y() ) ), true ); + } + + { + X x; + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, x ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, &x ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, std::ref(x) ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, std::cref(x) ) ), true ); + } + + { + Y y; + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, y ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, &y ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, std::ref(y) ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, std::cref(y) ) ), true ); + } + + { + X const x = {}; + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, x ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, &x ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, std::ref(x) ) ), true ); + } + + { + Y const y = {}; + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, y ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, &y ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::m, std::ref(y) ) ), true ); + } + + return boost::report_errors(); +} diff --git a/test/invoke_mfn_noexcept_test.cpp b/test/invoke_mfn_noexcept_test.cpp new file mode 100644 index 0000000..c1241be --- /dev/null +++ b/test/invoke_mfn_noexcept_test.cpp @@ -0,0 +1,134 @@ +// Copyright 2024 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#if !defined(__cpp_noexcept_function_type) + +BOOST_PRAGMA_MESSAGE( "Test skipped, __cpp_noexcept_function_type is not defined" ) +int main() {} + +#else + +#include +#include +#include + +struct X +{ + int f0() + { + return -1; + } + + int f1( int x1 ) noexcept + { + return x1; + } + + int f2( int x1, int x2 ) const + { + return 10*x1+x2; + } + + int f3( int x1, int x2, int x3 ) const noexcept + { + return 100*x1 + 10*x2 + x3; + } +}; + +struct Y: public virtual X +{ +}; + +int main() +{ + { + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f0, X() ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f1, X(), 1 ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, X(), 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, X(), 1, 2, 3 ) ), true ); + } + + { + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f0, Y() ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f1, Y(), 1 ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, Y(), 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, Y(), 1, 2, 3 ) ), true ); + } + + { + X x; + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f0, x ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f1, x, 1 ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, x, 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, x, 1, 2, 3 ) ), true ); + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f0, &x ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f1, &x, 1 ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, &x, 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, &x, 1, 2, 3 ) ), true ); + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f0, std::ref(x) ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f1, std::ref(x), 1 ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, std::ref(x), 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, std::ref(x), 1, 2, 3 ) ), true ); + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, std::cref(x), 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, std::cref(x), 1, 2, 3 ) ), true ); + } + + { + Y y; + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f0, y ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f1, y, 1 ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, y, 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, y, 1, 2, 3 ) ), true ); + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f0, &y ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f1, &y, 1 ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, &y, 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, &y, 1, 2, 3 ) ), true ); + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f0, std::ref(y) ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f1, std::ref(y), 1 ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, std::ref(y), 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, std::ref(y), 1, 2, 3 ) ), true ); + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, std::cref(y), 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, std::cref(y), 1, 2, 3 ) ), true ); + } + + { + X const x = {}; + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, x, 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, x, 1, 2, 3 ) ), true ); + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, &x, 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, &x, 1, 2, 3 ) ), true ); + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, std::ref(x), 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, std::ref(x), 1, 2, 3 ) ), true ); + } + + { + Y const y = {}; + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, y, 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, y, 1, 2, 3 ) ), true ); + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, &y, 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, &y, 1, 2, 3 ) ), true ); + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f2, std::ref(y), 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( &X::f3, std::ref(y), 1, 2, 3 ) ), true ); + } + + return boost::report_errors(); +} + +#endif diff --git a/test/invoke_obj_noexcept_test.cpp b/test/invoke_obj_noexcept_test.cpp new file mode 100644 index 0000000..ce8ffbe --- /dev/null +++ b/test/invoke_obj_noexcept_test.cpp @@ -0,0 +1,57 @@ +// Copyright 2024 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +struct F +{ + int operator()() + { + return -1; + } + + int operator()( int x1 ) noexcept + { + return x1; + } + + int operator()( int x1, int x2 ) const + { + return 10*x1+x2; + } + + int operator()( int x1, int x2, int x3 ) const noexcept + { + return 100*x1 + 10*x2 + x3; + } +}; + +int main() +{ + { + BOOST_TEST_EQ( noexcept( boost::compat::invoke( F() ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( F(), 1 ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( F(), 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( F(), 1, 2, 3 ) ), true ); + } + + { + F f = {}; + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( f ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( f, 1 ) ), true ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( f, 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( f, 1, 2, 3 ) ), true ); + } + + { + F const f = {}; + + BOOST_TEST_EQ( noexcept( boost::compat::invoke( f, 1, 2 ) ), false ); + BOOST_TEST_EQ( noexcept( boost::compat::invoke( f, 1, 2, 3 ) ), true ); + } + + return boost::report_errors(); +}