diff --git a/include/boost/compat/bind_back.hpp b/include/boost/compat/bind_back.hpp new file mode 100644 index 0000000..774d07a --- /dev/null +++ b/include/boost/compat/bind_back.hpp @@ -0,0 +1,72 @@ +#ifndef BOOST_COMPAT_BIND_BACK_HPP_INCLUDED +#define BOOST_COMPAT_BIND_BACK_HPP_INCLUDED + +// Copyright 2024 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace compat { + +namespace detail { + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1910) +# pragma warning(push) +# pragma warning(disable: 4100) // 'a': unreferenced formal parameter +#endif + +template +static constexpr auto invoke_bind_back_( F&& f, A&& a, index_sequence, B&&... b ) + BOOST_COMPAT_RETURNS( compat::invoke( std::forward(f), std::forward(b)..., std::get( std::forward(a) )... ) ) + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1910) +# pragma warning(pop) +#endif + +template class bind_back_ +{ +private: + + F f_; + std::tuple a_; + +public: + + template + constexpr bind_back_( F2&& f2, A2&&... a2 ): f_( std::forward(f2) ), a_( std::forward(a2)... ) {} + +public: + + template BOOST_CXX14_CONSTEXPR auto operator()( B&&... b ) & + BOOST_COMPAT_RETURNS( detail::invoke_bind_back_( f_, a_, make_index_sequence(), std::forward(b)... ) ) + + template constexpr auto operator()( B&&... b ) const & + BOOST_COMPAT_RETURNS( detail::invoke_bind_back_( f_, a_, make_index_sequence(), std::forward(b)... ) ) + + template BOOST_CXX14_CONSTEXPR auto operator()( B&&... b ) && + BOOST_COMPAT_RETURNS( detail::invoke_bind_back_( std::move(f_), std::move(a_), make_index_sequence(), std::forward(b)... ) ) + + template constexpr auto operator()( B&&... b ) const && + BOOST_COMPAT_RETURNS( detail::invoke_bind_back_( std::move(f_), std::move(a_), make_index_sequence(), std::forward(b)... ) ) +}; + +} // namespace detail + +template constexpr auto bind_back( F&& f, A&&... a ) -> detail::bind_back_< decay_t, decay_t... > +{ + return { std::forward(f), std::forward(a)... }; +} + +} // namespace compat +} // namespace boost + +#endif // BOOST_COMPAT_BIND_BACK_HPP_INCLUDED diff --git a/test/Jamfile b/test/Jamfile index 3a6fe13..b0c886d 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -64,3 +64,8 @@ compile bind_front_mfn_constexpr_test.cpp ; compile bind_front_md_constexpr_test.cpp ; run integer_sequence_test.cpp ; + +run bind_back_fn_test.cpp ; +run bind_back_obj_test.cpp ; +run bind_back_mfn_test.cpp ; +run bind_back_md_test.cpp ; diff --git a/test/bind_back_fn_test.cpp b/test/bind_back_fn_test.cpp new file mode 100644 index 0000000..844696c --- /dev/null +++ b/test/bind_back_fn_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 + +#if defined(__GNUC__) && __GNUC__ == 7 +# pragma GCC diagnostic ignored "-Wnoexcept-type" +#endif + +#include +#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 g( std::unique_ptr p, std::unique_ptr q ) +{ + return 10 * *p + *q; +} + +int main() +{ + BOOST_TEST_EQ( boost::compat::bind_back( f0 )(), -1 ); + BOOST_TEST_EQ( boost::compat::bind_back( f1 )( 1 ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( f2 )( 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( f3 )( 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( f1, 1 )(), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( f2, 1 )( 2 ), 21 ); + BOOST_TEST_EQ( boost::compat::bind_back( f3, 1 )( 2, 3 ), 231 ); + + BOOST_TEST_EQ( boost::compat::bind_back( f2, 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( f3, 1, 2 )( 3 ), 312 ); + + BOOST_TEST_EQ( boost::compat::bind_back( f3, 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( g, std::unique_ptr( new int(1) ) )( std::unique_ptr( new int(2) ) ), 21 ); + + return boost::report_errors(); +} diff --git a/test/bind_back_md_test.cpp b/test/bind_back_md_test.cpp new file mode 100644 index 0000000..c26fee0 --- /dev/null +++ b/test/bind_back_md_test.cpp @@ -0,0 +1,101 @@ +// 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( boost::compat::bind_back( &X::m, X() )(), -1 ); + } + + { + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, Y() )(), -1 ); + } + + { + X x; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, x )(), -1 ); + } + + { + X x; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, &x )(), -1 ); + boost::compat::bind_back( &X::m, &x )() = +1; + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, &x )(), +1 ); + } + + { + X x; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, std::ref(x) )(), -1 ); + boost::compat::bind_back( &X::m, std::ref(x) )() = +1; + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, std::ref(x) )(), +1 ); + } + + { + X x; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, std::cref(x) )(), -1 ); + } + + { + Y y; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, y )(), -1 ); + } + + { + Y y; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, &y )(), -1 ); + boost::compat::bind_back( &X::m, &y )() = +1; + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, &y )(), +1 ); + } + + { + Y y; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, std::ref(y) )(), -1 ); + boost::compat::bind_back( &X::m, std::ref(y) )() = +1; + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, std::ref(y) )(), +1 ); + } + + { + Y y; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, std::cref(y) )(), -1 ); + } + + { + X const x = {}; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, x )(), -1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, &x )(), -1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, std::ref(x) )(), -1 ); + } + + { + Y const y = {}; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, y )(), -1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, &y )(), -1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::m, std::ref(y) )(), -1 ); + } + + return boost::report_errors(); +} diff --git a/test/bind_back_mfn_test.cpp b/test/bind_back_mfn_test.cpp new file mode 100644 index 0000000..da6667b --- /dev/null +++ b/test/bind_back_mfn_test.cpp @@ -0,0 +1,308 @@ +// Copyright 2024 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#if defined(__GNUC__) && __GNUC__ == 7 +# pragma GCC diagnostic ignored "-Wnoexcept-type" +#endif + +#include +#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( boost::compat::bind_back( &X::f0 )( X() ), -1 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1 )( X(), 1 ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( X(), 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( X(), 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, X(), 1 )(), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, X(), 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, X(), 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, 1 )( X() ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( X() ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( X() ), 123 ); + } + + { + BOOST_TEST_EQ( boost::compat::bind_back( &X::f0 )( Y() ), -1 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1 )( Y(), 1 ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( Y(), 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( Y(), 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, Y(), 1 )(), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, Y(), 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, Y(), 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, 1 )( Y() ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( Y() ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( Y() ), 123 ); + } + + { + X x; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f0 )( x ), -1 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1 )( x, 1 ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( x, 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( x, 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, x, 1 )(), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, x, 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, x, 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, 1 )( x ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( x ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( x ), 123 ); + } + + { + Y x; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f0 )( x ), -1 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1 )( x, 1 ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( x, 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( x, 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, x, 1 )(), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, x, 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, x, 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, 1 )( x ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( x ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( x ), 123 ); + } + + { + X x; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f0 )( &x ), -1 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1 )( &x, 1 ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( &x, 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( &x, 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, &x, 1 )(), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, &x, 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, &x, 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, 1 )( &x ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( &x ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( &x ), 123 ); + } + + { + Y x; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f0 )( &x ), -1 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1 )( &x, 1 ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( &x, 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( &x, 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, &x, 1 )(), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, &x, 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, &x, 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, 1 )( &x ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( &x ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( &x ), 123 ); + } + + { + X x; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f0 )( std::ref(x) ), -1 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1 )( std::ref(x), 1 ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( std::ref(x), 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( std::ref(x), 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, std::ref(x), 1 )(), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, std::ref(x), 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, std::ref(x), 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, 1 )( std::ref(x) ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( std::ref(x) ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( std::ref(x) ), 123 ); + } + + { + Y x; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f0 )( std::ref(x) ), -1 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1 )( std::ref(x), 1 ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( std::ref(x), 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( std::ref(x), 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, std::ref(x), 1 )(), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, std::ref(x), 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, std::ref(x), 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f1, 1 )( std::ref(x) ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( std::ref(x) ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( std::ref(x) ), 123 ); + } + + { + X x; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( std::cref(x), 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( std::cref(x), 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, std::cref(x), 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, std::cref(x), 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( std::cref(x) ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( std::cref(x) ), 123 ); + } + + { + Y x; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( std::cref(x), 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( std::cref(x), 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, std::cref(x), 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, std::cref(x), 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( std::cref(x) ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( std::cref(x) ), 123 ); + } + + { + X const x = {}; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( x, 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( x, 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, x, 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, x, 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( x ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( x ), 123 ); + } + + { + Y const x = {}; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( x, 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( x, 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, x, 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, x, 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( x ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( x ), 123 ); + } + + { + X const x = {}; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( &x, 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( &x, 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, &x, 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, &x, 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( &x ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( &x ), 123 ); + } + + { + Y const x = {}; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( &x, 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( &x, 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, &x, 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, &x, 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( &x ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( &x ), 123 ); + } + + { + X const x = {}; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( std::ref(x), 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( std::ref(x), 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, std::ref(x), 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, std::ref(x), 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( std::ref(x) ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( std::ref(x) ), 123 ); + } + + { + Y const x = {}; + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2 )( std::ref(x), 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3 )( std::ref(x), 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, std::ref(x), 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, std::ref(x), 1, 2, 3 )(), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( &X::f2, 1, 2 )( std::ref(x) ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( std::ref(x) ), 123 ); + } + + { + std::unique_ptr px( new X ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( std::move(px) ), 123 ); + } + + { + std::unique_ptr px( new Y ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, 1, 2, 3 )( std::move(px) ), 123 ); + } + + { + std::unique_ptr px( new X ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, std::move(px), 1, 2, 3 )(), 123 ); + } + + { + std::unique_ptr px( new Y ); + BOOST_TEST_EQ( boost::compat::bind_back( &X::f3, std::move(px), 1, 2, 3 )(), 123 ); + } + + return boost::report_errors(); +} diff --git a/test/bind_back_obj_test.cpp b/test/bind_back_obj_test.cpp new file mode 100644 index 0000000..cf62f78 --- /dev/null +++ b/test/bind_back_obj_test.cpp @@ -0,0 +1,101 @@ +// Copyright 2024 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +struct F1 +{ + 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; + } +}; + +struct F2 +{ + int operator()( int x1, int x2 ) & + { + return 100*x1 + 10*x2 + 1; + } + + int operator()( int x1, int x2 ) const & + { + return 100*x1 + 10*x2 + 2; + } + int operator()( int x1, int x2 ) && + { + return 100*x1 + 10*x2 + 3; + } + int operator()( int x1, int x2 ) const && + { + return 100*x1 + 10*x2 + 4; + } +}; + +int main() +{ + { + BOOST_TEST_EQ( boost::compat::bind_back( F1() )(), -1 ); + BOOST_TEST_EQ( boost::compat::bind_back( F1() )( 1 ), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( F1() )( 1, 2 ), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( F1() )( 1, 2, 3 ), 123 ); + + BOOST_TEST_EQ( boost::compat::bind_back( F1(), 1 )(), 1 ); + BOOST_TEST_EQ( boost::compat::bind_back( F1(), 1 )( 2 ), 21 ); + BOOST_TEST_EQ( boost::compat::bind_back( F1(), 1 )( 2, 3 ), 231 ); + + BOOST_TEST_EQ( boost::compat::bind_back( F1(), 1, 2 )(), 12 ); + BOOST_TEST_EQ( boost::compat::bind_back( F1(), 1, 2 )( 3 ), 312 ); + + BOOST_TEST_EQ( boost::compat::bind_back( F1(), 1, 2, 3 )(), 123 ); + } + + { + BOOST_TEST_EQ( boost::compat::bind_back( F2(), 9 )( 8 ), 893 ); + } + + { + auto fn = boost::compat::bind_back( F2(), 9 ); + BOOST_TEST_EQ( fn( 8 ), 891 ); + } + + { + auto const fn = boost::compat::bind_back( F2(), 9 ); + BOOST_TEST_EQ( fn( 8 ), 892 ); + } + + { + auto fn = boost::compat::bind_back( F2(), 9 ); + BOOST_TEST_EQ( std::move( fn )( 8 ), 893 ); + } + +#if !BOOST_WORKAROUND(BOOST_GCC, < 40900) + + { + auto const fn = boost::compat::bind_back( F2(), 9 ); + BOOST_TEST_EQ( std::move( fn )( 8 ), 894 ); + } + +#endif + + return boost::report_errors(); +} diff --git a/test/quick.cpp b/test/quick.cpp index 494fbee..adf2d42 100644 --- a/test/quick.cpp +++ b/test/quick.cpp @@ -6,6 +6,7 @@ #include #include #include +#include int main() {