From c61d480cb637dffa264b0aa055f38cd32384dcfe Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 18 Oct 2001 15:05:57 +0000 Subject: [PATCH] Return type can now be omitted on adaptable function objects [SVN r11401] --- bind.html | 62 +++++++++++-- bind_test.cpp | 20 ++++ include/boost/bind.hpp | 202 ++++++++++++++++++++++++++++++++--------- 3 files changed, 230 insertions(+), 54 deletions(-) diff --git a/bind.html b/bind.html index e9889c4..49f8018 100644 --- a/bind.html +++ b/bind.html @@ -17,7 +17,7 @@ - +

bind.hpp

 1.01.0001 (2001-09-02)
 1.02.0001 (2001-10-18)
@@ -108,6 +108,14 @@ bind(g, _3, _3, _3)(x, y, z); // g(z, z, z) bind(g, _1, _1, _1)(x, y, z); // g(x, x, x) +

+Note that, in the last example, the function object produced by +bind(g, _1, _1, _1) does not contain references to any arguments +beyond the first, but it can still be used with more than one argument. +Any extra arguments are silently ignored, just like the first and the second +argument are ignored in the third example. +

+

The arguments that bind takes are copied and held internally by the returned function object. For example, in the following code: @@ -135,10 +143,10 @@ bind(f, ref(i), _1);

Using bind with function objects

-Any function object can be passed as a first argument to bind, but the -syntax is a bit different. The return type of the generated function object's +bind is not limited to functions; it accepts arbitrary function objects. +In the general case, the return type of the generated function object's operator() has to be specified explicitly (without a typeof -operator the return type cannot be inferred in the general case): +operator the return type cannot be inferred):

@@ -156,11 +164,18 @@ bind<int>(f, _1, _1)(x);               // f(x, x), i.e. zero
 

-[Note: when, hopefully, - -function template default arguments become part of C++, -bind will no longer require the explicit specification of the return type -when the function object defines result_type.] +When the function object exposes a nested type named result_type, +the explicit return type can be omitted: +

+ +
+int x = 8;
+
+bind(std::less<int>, _1, 9)(x);               // x < 9
+
+ +

+[Note: the ability to omit the return type is not available on all compilers.]

Using bind with member function pointers

@@ -392,12 +407,16 @@ namespace boost template<class R, class F> implementation-defined-1 bind(F f); +template<class F> implementation-defined-1-1 bind(F f); + template<class R> implementation-defined-2 bind(R (*f) ()); // one argument template<class R, class F, class A1> implementation-defined-3 bind(F f, A1 a1); +template<class F, class A1> implementation-defined-3-1 bind(F f, A1 a1); + template<class R, class B1, class A1> implementation-defined-4 bind(R (*f) (B1), A1 a1); template<class R, class T, class A1> implementation-defined-5 bind(R (T::*f) (), A1 a1); @@ -408,6 +427,8 @@ template<class R, class T, class A1> implementation-defined-6 implementation-defined-7 bind(F f, A1 a1, A2 a2); +template<class F, class A1, class A2> implementation-defined-7-1 bind(F f, A1 a1, A2 a2); + template<class R, class B1, class B2, class A1, class A2> implementation-defined-8 bind(R (*f) (B1, B2), A1 a1, A2 a2); template<class R, class T, class B1, class A1, class A2> implementation-defined-9 bind(R (T::*f) (B1), A1 a1, A2 a2); @@ -474,6 +495,12 @@ implicitly converted to R. Throws: Nothing unless the copy constructor of F throws an exception.

+

template<class F> implementation-defined-1-1 bind(F f)

+ +

+Effects: equivalent to bind<typename F::result_type, F>(f); +

+

template<class R> implementation-defined-2 bind(R (*f) ())

@@ -496,6 +523,12 @@ implicitly converted to R. Throws: Nothing unless the copy constructors of F and A1 throw an exception.

+

template<class F, class A1> implementation-defined-3-1 bind(F f, A1 a1)

+ +

+Effects: equivalent to bind<typename F::result_type, F, A1>(f, a1); +

+

template<class R, class B1, class A1> implementation-defined-4 bind(R (*f) (B1), A1 a1)

@@ -531,6 +564,12 @@ implicitly converted to R. Throws: Nothing unless the copy constructors of F, A1 and A2 throw an exception.

+

template<class F, class A1, class A2> implementation-defined-7-1 bind(F f, A1 a1, A2 a2)

+ +

+Effects: equivalent to bind<typename F::result_type, F, A1, A2>(f, a1, a2); +

+

template<class R, class B1, class B2, class A1, class A2> implementation-defined-8 bind(R (*f) (B1, B2), A1 a1, A2 a2)

@@ -693,6 +732,11 @@ was Darin Adler. The precise semantics of bind were refined in discussions with Jaakko Järvi.

+

+Dave Abrahams fixed a MSVC-specific conflict between bind and the +iterator adaptors library. +

+




Copyright © 2001 by Peter Dimov and Multi Media Ltd. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document diff --git a/bind_test.cpp b/bind_test.cpp index d71a838..8e9d276 100644 --- a/bind_test.cpp +++ b/bind_test.cpp @@ -120,6 +120,23 @@ void function_object_test() // +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + +struct Z +{ + typedef int result_type; + int operator()(int a, int b) const { return a + 10 * b; } +}; + +void adaptable_function_object_test() +{ + BOOST_TEST( boost::bind(Z(), 7, 4)() == 47 ); +} + +#endif + +// + struct X { mutable unsigned int hash; @@ -262,6 +279,9 @@ int test_main(int, char * []) { function_test(); function_object_test(); +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + adaptable_function_object_test(); +#endif member_function_test(); nested_bind_test(); diff --git a/include/boost/bind.hpp b/include/boost/bind.hpp index 27e7c0b..0ac926c 100644 --- a/include/boost/bind.hpp +++ b/include/boost/bind.hpp @@ -8,7 +8,7 @@ // // bind.hpp - binds function objects to arguments // -// Version 1.01.0001 (2001-08-29) +// Version 1.02.0001 (2001-10-18) // // Copyright (c) 2001 Peter Dimov and Multi Media Ltd. // @@ -512,144 +512,170 @@ private: list9 & operator= (list9 const &); }; +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + +// unspecified + +struct unspecified {}; + +template struct result_traits +{ + typedef R type; +}; + +template struct result_traits +{ + typedef typename F::result_type type; +}; + +#endif + // bind_t template class bind_t { public: +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + + typedef typename result_traits::type result_type; + +#else + typedef R result_type; +#endif + bind_t(F f, L const & l): f_(f), l_(l) {} - R operator()() + result_type operator()() { list0 a; - return l_(type(), f_, a); + return l_(type(), f_, a); } - R operator()() const + result_type operator()() const { list0 a; - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1) + template result_type operator()(A1 & a1) { list1 a(a1); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1) const + template result_type operator()(A1 & a1) const { list1 a(a1); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2) + template result_type operator()(A1 & a1, A2 & a2) { list2 a(a1, a2); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2) const + template result_type operator()(A1 & a1, A2 & a2) const { list2 a(a1, a2); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2, A3 & a3) + template result_type operator()(A1 & a1, A2 & a2, A3 & a3) { list3 a(a1, a2, a3); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2, A3 & a3) const + template result_type operator()(A1 & a1, A2 & a2, A3 & a3) const { list3 a(a1, a2, a3); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4) + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4) { list4 a(a1, a2, a3, a4); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4) const + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4) const { list4 a(a1, a2, a3, a4); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5) + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5) { list5 a(a1, a2, a3, a4, a5); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5) const + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5) const { list5 a(a1, a2, a3, a4, a5); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6) + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6) { list6 a(a1, a2, a3, a4, a5, a6); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6) const + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6) const { list6 a(a1, a2, a3, a4, a5, a6); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7) + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7) { list7 a(a1, a2, a3, a4, a5, a6, a7); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7) const + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7) const { list7 a(a1, a2, a3, a4, a5, a6, a7); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8) + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8) { list8 a(a1, a2, a3, a4, a5, a6, a7, a8); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8) const + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8) const { list8 a(a1, a2, a3, a4, a5, a6, a7, a8); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9) + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9) { list9 a(a1, a2, a3, a4, a5, a6, a7, a8, a9); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9) const + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9) const { list9 a(a1, a2, a3, a4, a5, a6, a7, a8, a9); - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R eval(A & a) + template result_type eval(A & a) { - return l_(type(), f_, a); + return l_(type(), f_, a); } - template R eval(A & a) const + template result_type eval(A & a) const { - return l_(type(), f_, a); + return l_(type(), f_, a); } template void accept(V & v) const @@ -915,6 +941,92 @@ template(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); } +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + +// adaptable function objects + +template + _bi::bind_t<_bi::unspecified, F, _bi::list0> + BOOST_BIND(F f) +{ + typedef _bi::list0 list_type; + return _bi::bind_t<_bi::unspecified, F, list_type> (f, list_type()); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_1::type> + BOOST_BIND(F f, A1 a1) +{ + typedef typename _bi::list_av_1::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type> (f, list_type(a1)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_2::type> + BOOST_BIND(F f, A1 a1, A2 a2) +{ + typedef typename _bi::list_av_2::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type> (f, list_type(a1, a2)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_3::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3) +{ + typedef typename _bi::list_av_3::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_4::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4) +{ + typedef typename _bi::list_av_4::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_5::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) +{ + typedef typename _bi::list_av_5::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_6::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) +{ + typedef typename _bi::list_av_6::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_7::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) +{ + typedef typename _bi::list_av_7::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_8::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) +{ + typedef typename _bi::list_av_8::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_9::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) +{ + typedef typename _bi::list_av_9::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); +} + +#endif + // function pointers template