Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r62627 - in trunk: boost/lambda/detail libs/lambda/test
From: steven_at_[hidden]
Date: 2010-06-08 21:39:49


Author: steven_watanabe
Date: 2010-06-08 21:39:48 EDT (Tue, 08 Jun 2010)
New Revision: 62627
URL: http://svn.boost.org/trac/boost/changeset/62627

Log:
Enable using result_of with Boost.Lambda. Fixes #426. Fixes #864
Added:
   trunk/libs/lambda/test/result_of_tests.cpp (contents, props changed)
Text files modified:
   trunk/boost/lambda/detail/function_adaptors.hpp | 158 +++++++++++++++++++++++++++++++++++++--
   trunk/boost/lambda/detail/lambda_functor_base.hpp | 2
   trunk/boost/lambda/detail/lambda_functors.hpp | 19 ++++
   trunk/boost/lambda/detail/return_type_traits.hpp | 2
   trunk/libs/lambda/test/Jamfile | 1
   trunk/libs/lambda/test/bind_tests_advanced.cpp | 67 +++++++++++++---
   6 files changed, 226 insertions(+), 23 deletions(-)

Modified: trunk/boost/lambda/detail/function_adaptors.hpp
==============================================================================
--- trunk/boost/lambda/detail/function_adaptors.hpp (original)
+++ trunk/boost/lambda/detail/function_adaptors.hpp 2010-06-08 21:39:48 EDT (Tue, 08 Jun 2010)
@@ -12,25 +12,167 @@
 #ifndef BOOST_LAMBDA_FUNCTION_ADAPTORS_HPP
 #define BOOST_LAMBDA_FUNCTION_ADAPTORS_HPP
 
+#include "boost/mpl/has_xxx.hpp"
+#include "boost/tuple/tuple.hpp"
 #include "boost/type_traits/same_traits.hpp"
+#include "boost/type_traits/remove_reference.hpp"
+#include "boost/utility/result_of.hpp"
 
 namespace boost {
 namespace lambda {
 
+namespace detail {
+
+BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(has_template_sig, sig, 1, true)
+
+template<class Tuple>
+struct remove_references_from_elements {
+ typedef typename boost::tuples::cons<
+ typename boost::remove_reference<typename Tuple::head_type>::type,
+ typename remove_references_from_elements<typename Tuple::tail_type>::type
+ > type;
+};
+
+template<>
+struct remove_references_from_elements<boost::tuples::null_type> {
+ typedef boost::tuples::null_type type;
+};
+
+}
+
 template <class Func> struct function_adaptor {
 
+ typedef typename detail::remove_reference_and_cv<Func>::type plainF;
+
+#if !defined(BOOST_NO_RESULT_OF)
+ // Support functors that use the boost::result_of return type convention.
+ template<class Tuple, int Length, bool HasSig>
+ struct result_converter;
+ template<class Tuple, int Length>
+ struct result_converter<Tuple, Length, true>
+ : plainF::template sig<
+ typename detail::remove_references_from_elements<Tuple>::type
+ >
+ {};
+ template<class Tuple>
+ struct result_converter<Tuple, 0, false>
+ : result_of<plainF()>
+ {};
+ template<class Tuple>
+ struct result_converter<Tuple, 1, false>
+ : result_of<plainF(
+ typename tuples::element<1, Tuple>::type)
+ >
+ {};
+ template<class Tuple>
+ struct result_converter<Tuple, 2, false>
+ : result_of<plainF(
+ typename tuples::element<1, Tuple>::type,
+ typename tuples::element<2, Tuple>::type)
+ >
+ {};
+ template<class Tuple>
+ struct result_converter<Tuple, 3, false>
+ : result_of<plainF(
+ typename tuples::element<1, Tuple>::type,
+ typename tuples::element<2, Tuple>::type,
+ typename tuples::element<3, Tuple>::type)
+ >
+ {};
+ template<class Tuple>
+ struct result_converter<Tuple, 4, false>
+ : result_of<plainF(
+ typename tuples::element<1, Tuple>::type,
+ typename tuples::element<2, Tuple>::type,
+ typename tuples::element<3, Tuple>::type,
+ typename tuples::element<4, Tuple>::type)
+ >
+ {};
+ template<class Tuple>
+ struct result_converter<Tuple, 5, false>
+ : result_of<plainF(
+ typename tuples::element<1, Tuple>::type,
+ typename tuples::element<2, Tuple>::type,
+ typename tuples::element<3, Tuple>::type,
+ typename tuples::element<4, Tuple>::type,
+ typename tuples::element<5, Tuple>::type)
+ >
+ {};
+ template<class Tuple>
+ struct result_converter<Tuple, 6, false>
+ : result_of<plainF(
+ typename tuples::element<1, Tuple>::type,
+ typename tuples::element<2, Tuple>::type,
+ typename tuples::element<3, Tuple>::type,
+ typename tuples::element<4, Tuple>::type,
+ typename tuples::element<5, Tuple>::type,
+ typename tuples::element<6, Tuple>::type)
+ >
+ {};
+ template<class Tuple>
+ struct result_converter<Tuple, 7, false>
+ : result_of<plainF(
+ typename tuples::element<1, Tuple>::type,
+ typename tuples::element<2, Tuple>::type,
+ typename tuples::element<3, Tuple>::type,
+ typename tuples::element<4, Tuple>::type,
+ typename tuples::element<5, Tuple>::type,
+ typename tuples::element<6, Tuple>::type,
+ typename tuples::element<7, Tuple>::type)
+ >
+ {};
+ template<class Tuple>
+ struct result_converter<Tuple, 8, false>
+ : result_of<plainF(
+ typename tuples::element<1, Tuple>::type,
+ typename tuples::element<2, Tuple>::type,
+ typename tuples::element<3, Tuple>::type,
+ typename tuples::element<4, Tuple>::type,
+ typename tuples::element<5, Tuple>::type,
+ typename tuples::element<6, Tuple>::type,
+ typename tuples::element<7, Tuple>::type,
+ typename tuples::element<8, Tuple>::type)
+ >
+ {};
+ template<class Tuple>
+ struct result_converter<Tuple, 9, false>
+ : result_of<plainF(
+ typename tuples::element<1, Tuple>::type,
+ typename tuples::element<2, Tuple>::type,
+ typename tuples::element<3, Tuple>::type,
+ typename tuples::element<4, Tuple>::type,
+ typename tuples::element<5, Tuple>::type,
+ typename tuples::element<6, Tuple>::type,
+ typename tuples::element<7, Tuple>::type,
+ typename tuples::element<8, Tuple>::type,
+ typename tuples::element<9, Tuple>::type)
+ >
+ {};
+
   // we do not know the return type off-hand, we must ask it from Func
- template <class Args> class sig {
- typedef typename Args::head_type F;
+ // To sig we pass a cons list, where the head is the function object type
+ // itself (potentially cv-qualified)
+ // and the tail contains the types of the actual arguments to be passed
+ // to the function object. The arguments can be cv qualified
+ // as well.
+ template <class Args>
+ struct sig
+ : result_converter<
+ Args
+ , tuples::length<typename Args::tail_type>::value
+ , detail::has_template_sig<plainF, Args>::value
+ >
+ {};
+#else // BOOST_NO_RESULT_OF
+
+ template <class Args> class sig {
     typedef typename detail::remove_reference_and_cv<Func>::type plainF;
   public:
- // To sig we pass a cons list, where the head is the function object type
- // itself (potentially cv-qualified)
- // and the tail contains the types of the actual arguments to be passed
- // to the function object. The arguments can be cv qualified
- // as well.
- typedef typename plainF::template sig<Args>::type type;
+ typedef typename plainF::template sig<
+ typename detail::remove_references_from_elements<Args>::type
+ >::type type;
   };
+#endif
 
   template<class RET, class A1>
   static RET apply(A1& a1) {

Modified: trunk/boost/lambda/detail/lambda_functor_base.hpp
==============================================================================
--- trunk/boost/lambda/detail/lambda_functor_base.hpp (original)
+++ trunk/boost/lambda/detail/lambda_functor_base.hpp 2010-06-08 21:39:48 EDT (Tue, 08 Jun 2010)
@@ -383,7 +383,7 @@
                                                                        \
   template<class SigArgs> struct sig { \
     typedef typename \
- detail::deduce_non_ref_argument_types<Args, SigArgs>::type rets_t; \
+ detail::deduce_argument_types<Args, SigArgs>::type rets_t; \
   public: \
     typedef typename \
       return_type_N_prot<Act, rets_t>::type type; \

Modified: trunk/boost/lambda/detail/lambda_functors.hpp
==============================================================================
--- trunk/boost/lambda/detail/lambda_functors.hpp (original)
+++ trunk/boost/lambda/detail/lambda_functors.hpp 2010-06-08 21:39:48 EDT (Tue, 08 Jun 2010)
@@ -161,6 +161,25 @@
     inherited::template sig<null_type>::type
       nullary_return_type;
 
+ // Support for boost::result_of.
+ template <class Sig> struct result;
+ template <class F>
+ struct result<F()> {
+ typedef nullary_return_type type;
+ };
+ template <class F, class A>
+ struct result<F(A)> {
+ typedef typename sig<tuple<F, A> >::type type;
+ };
+ template <class F, class A, class B>
+ struct result<F(A, B)> {
+ typedef typename sig<tuple<F, A, B> >::type type;
+ };
+ template <class F, class A, class B, class C>
+ struct result<F(A, B, C)> {
+ typedef typename sig<tuple<F, A, B, C> >::type type;
+ };
+
   nullary_return_type operator()() const {
     return inherited::template
       call<nullary_return_type>

Modified: trunk/boost/lambda/detail/return_type_traits.hpp
==============================================================================
--- trunk/boost/lambda/detail/return_type_traits.hpp (original)
+++ trunk/boost/lambda/detail/return_type_traits.hpp 2010-06-08 21:39:48 EDT (Tue, 08 Jun 2010)
@@ -216,8 +216,6 @@
 
 
   // currently there are no protectable actions with > 2 args
- // Note, that if there will be, lambda_functor_base will have to be
- // changed to not get rid of references in Args elements
 
 template<class Act, class Args> struct return_type_N_prot {
   typedef typename return_type_N<Act, Args>::type type;

Modified: trunk/libs/lambda/test/Jamfile
==============================================================================
--- trunk/libs/lambda/test/Jamfile (original)
+++ trunk/libs/lambda/test/Jamfile 2010-06-08 21:39:48 EDT (Tue, 08 Jun 2010)
@@ -30,5 +30,6 @@
     [ run operator_tests_simple.cpp ]
     [ run phoenix_control_structures.cpp ]
     [ run switch_construct.cpp ]
+ [ run result_of_tests.cpp ]
     [ run ret_test.cpp ]
   ;

Modified: trunk/libs/lambda/test/bind_tests_advanced.cpp
==============================================================================
--- trunk/libs/lambda/test/bind_tests_advanced.cpp (original)
+++ trunk/libs/lambda/test/bind_tests_advanced.cpp 2010-06-08 21:39:48 EDT (Tue, 08 Jun 2010)
@@ -2,6 +2,7 @@
 //
 // Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi_at_[hidden])
 // Copyright (C) 2000-2003 Gary Powell (powellg_at_[hidden])
+// Copyright (C) 2010 Steven Watanabe
 //
 // Distributed under the Boost Software License, Version 1.0. (See
 // accompanying file LICENSE_1_0.txt or copy at
@@ -19,6 +20,9 @@
 
 
 #include "boost/any.hpp"
+#include "boost/type_traits/is_reference.hpp"
+#include "boost/mpl/assert.hpp"
+#include "boost/mpl/if.hpp"
 
 #include <iostream>
 
@@ -352,6 +356,55 @@
   BOOST_CHECK(i == 3);
 }
 
+template<class T>
+struct func {
+ template<class Args>
+ struct sig {
+ typedef typename boost::tuples::element<1, Args>::type arg1;
+ // If the argument type is not the same as the expected type,
+ // return void, which will cause an error. Note that we
+ // can't just assert that the types are the same, because
+ // both const and non-const versions can be instantiated
+ // even though only one is ultimately used.
+ typedef typename boost::mpl::if_<boost::is_same<arg1, T>,
+ typename boost::remove_const<arg1>::type,
+ void
+ >::type type;
+ };
+ template<class U>
+ U operator()(const U& arg) const {
+ return arg;
+ }
+};
+
+void test_sig()
+{
+ int i = 1;
+ BOOST_CHECK(bind(func<int>(), 1)() == 1);
+ BOOST_CHECK(bind(func<const int>(), _1)(static_cast<const int&>(i)) == 1);
+ BOOST_CHECK(bind(func<int>(), _1)(i) == 1);
+}
+
+class base {
+public:
+ virtual int foo() = 0;
+};
+
+class derived : public base {
+public:
+ virtual int foo() {
+ return 1;
+ }
+};
+
+void test_abstract()
+{
+ derived d;
+ base& b = d;
+ BOOST_CHECK(bind(&base::foo, var(b))() == 1);
+ BOOST_CHECK(bind(&base::foo, *_1)(&b) == 1);
+}
+
 int test_main(int, char *[]) {
 
   test_nested_binds();
@@ -361,17 +414,7 @@
   test_const_parameters();
   test_rvalue_arguments();
   test_break_const();
+ test_sig();
+ test_abstract();
   return 0;
 }
-
-
-
-
-
-
-
-
-
-
-
-

Added: trunk/libs/lambda/test/result_of_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/lambda/test/result_of_tests.cpp 2010-06-08 21:39:48 EDT (Tue, 08 Jun 2010)
@@ -0,0 +1,314 @@
+// result_of_tests.cpp -- The Boost Lambda Library ------------------
+//
+// Copyright (C) 2010 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+#include <boost/lambda/bind.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+struct with_result_type {
+ typedef int result_type;
+ int operator()() const { return 0; }
+ int operator()(int) const { return 1; }
+ int operator()(int, int) const { return 2; }
+ int operator()(int, int, int) const { return 3; }
+ int operator()(int, int, int, int) const { return 4; }
+ int operator()(int, int, int, int, int) const { return 5; }
+ int operator()(int, int, int, int, int, int) const { return 6; }
+ int operator()(int, int, int, int, int, int, int) const { return 7; }
+ int operator()(int, int, int, int, int, int, int, int) const { return 8; }
+ int operator()(int, int, int, int, int, int, int, int, int) const { return 9; }
+};
+
+struct with_result_template_value {
+ template<class Sig>
+ struct result;
+ template<class This>
+ struct result<This()> {
+ typedef int type;
+ };
+ template<class This, class A1>
+ struct result<This(A1)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2>
+ struct result<This(A1, A2)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3>
+ struct result<This(A1, A2, A3)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4>
+ struct result<This(A1, A2, A3, A4)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5>
+ struct result<This(A1, A2, A3, A4, A5)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6>
+ struct result<This(A1, A2, A3, A4, A5, A6)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+ struct result<This(A1, A2, A3, A4, A5, A6, A7)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A7, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+ struct result<This(A1, A2, A3, A4, A5, A6, A7, A8)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A7, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A8, int>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+ struct result<This(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A7, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A8, int>));
+ BOOST_MPL_ASSERT((boost::is_same<A9, int>));
+ typedef int type;
+ };
+
+ int operator()() const { return 0; }
+ int operator()(int) const { return 1; }
+ int operator()(int, int) const { return 2; }
+ int operator()(int, int, int) const { return 3; }
+ int operator()(int, int, int, int) const { return 4; }
+ int operator()(int, int, int, int, int) const { return 5; }
+ int operator()(int, int, int, int, int, int) const { return 6; }
+ int operator()(int, int, int, int, int, int, int) const { return 7; }
+ int operator()(int, int, int, int, int, int, int, int) const { return 8; }
+ int operator()(int, int, int, int, int, int, int, int, int) const { return 9; }
+};
+
+struct with_result_template_reference {
+ template<class Sig>
+ struct result;
+ template<class This>
+ struct result<This()> {
+ typedef int type;
+ };
+ template<class This, class A1>
+ struct result<This(A1)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2>
+ struct result<This(A1, A2)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3>
+ struct result<This(A1, A2, A3)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4>
+ struct result<This(A1, A2, A3, A4)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5>
+ struct result<This(A1, A2, A3, A4, A5)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6>
+ struct result<This(A1, A2, A3, A4, A5, A6)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+ struct result<This(A1, A2, A3, A4, A5, A6, A7)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A7, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+ struct result<This(A1, A2, A3, A4, A5, A6, A7, A8)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A7, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A8, int&>));
+ typedef int type;
+ };
+ template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+ struct result<This(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
+ BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A7, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A8, int&>));
+ BOOST_MPL_ASSERT((boost::is_same<A9, int&>));
+ typedef int type;
+ };
+
+ int operator()() const { return 0; }
+ int operator()(int) const { return 1; }
+ int operator()(int, int) const { return 2; }
+ int operator()(int, int, int) const { return 3; }
+ int operator()(int, int, int, int) const { return 4; }
+ int operator()(int, int, int, int, int) const { return 5; }
+ int operator()(int, int, int, int, int, int) const { return 6; }
+ int operator()(int, int, int, int, int, int, int) const { return 7; }
+ int operator()(int, int, int, int, int, int, int, int) const { return 8; }
+ int operator()(int, int, int, int, int, int, int, int, int) const { return 9; }
+};
+
+template<class F>
+typename boost::result_of<F()>::type apply0(F f) {
+ return f();
+}
+template<class A, class F>
+typename boost::result_of<F(A)>::type apply1(F f, A a) {
+ return f(a);
+}
+template<class A, class B, class F>
+typename boost::result_of<F(A, B)>::type apply2(F f, A a, B b) {
+ return f(a, b);
+}
+template<class A, class B, class C, class F>
+typename boost::result_of<F(A, B, C)>::type apply3(F f, A a, B b, C c) {
+ return f(a, b, c);
+}
+
+using namespace boost::lambda;
+
+int test_main(int, char *[]) {
+ BOOST_CHECK(boost::lambda::bind(with_result_type())() == 0);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1)() == 1);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2)() == 2);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3)() == 3);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4)() == 4);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5)() == 5);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6)() == 6);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7)() == 7);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7, 8)() == 8);
+ BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7, 8, 9)() == 9);
+
+ // Nullary result_of fails
+ //BOOST_CHECK(boost::lambda::bind(with_result_template_value())() == 0);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1)() == 1);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2)() == 2);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3)() == 3);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4)() == 4);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5)() == 5);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6)() == 6);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7)() == 7);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7, 8)() == 8);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7, 8, 9)() == 9);
+
+ int one = 1,
+ two = 2,
+ three = 3,
+ four = 4,
+ five = 5,
+ six = 6,
+ seven = 7,
+ eight = 8,
+ nine = 9;
+
+ // Nullary result_of fails
+ //BOOST_CHECK(boost::lambda::bind(with_result_template_reference())() == 0);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one))() == 1);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two))() == 2);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three))() == 3);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four))() == 4);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five))() == 5);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six))() == 6);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven))() == 7);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven), var(eight))() == 8);
+ BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven), var(eight), var(nine))() == 9);
+
+ // Check using result_of with lambda functors
+ //BOOST_CHECK(apply0(constant(0)) == 0);
+ BOOST_CHECK(apply1<int>(_1, one) == 1);
+ BOOST_CHECK(apply1<int&>(_1, one) == 1);
+ BOOST_CHECK(apply1<const int&>(_1, one) == 1);
+ BOOST_CHECK((apply2<int, int>(_1 + _2, one, two) == 3));
+ BOOST_CHECK((apply2<int&, int&>(_1 + _2, one, two) == 3));
+ BOOST_CHECK((apply2<const int&, const int&>(_1 + _2, one, two) == 3));
+ BOOST_CHECK((apply3<int, int, int>(_1 + _2 + _3, one, two, three) == 6));
+ BOOST_CHECK((apply3<int&, int&, int&>(_1 + _2 + _3, one, two, three) == 6));
+ BOOST_CHECK((apply3<const int&, const int&, const int&>(_1 + _2 + _3, one, two, three) == 6));
+
+ return 0;
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk