From 7bfc1a8d02fe3dfb4d0d3a9c20c18f0e72c597e4 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 12 Feb 2003 22:00:52 +0000 Subject: [PATCH] Version of boost::ref that supports function objects directly, along with an extensive set of test code. [SVN r956] --- include/boost/ref.hpp | 688 ++++++++++++++++++++++++++++++++++++++++++ ref_call_test.cpp | 540 +++++++++++++++++++++++++++++++++ 2 files changed, 1228 insertions(+) create mode 100644 include/boost/ref.hpp create mode 100644 ref_call_test.cpp diff --git a/include/boost/ref.hpp b/include/boost/ref.hpp new file mode 100644 index 0000000..fba17d2 --- /dev/null +++ b/include/boost/ref.hpp @@ -0,0 +1,688 @@ +#ifndef BOOST_REF_HPP_INCLUDED +# define BOOST_REF_HPP_INCLUDED + +# if _MSC_VER+0 >= 1020 +# pragma once +# endif + +# include +# include +# include +# include + +// +// ref.hpp - ref/cref, useful helper functions +// +// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi) +// Copyright (C) 2001, 2002 Peter Dimov +// Copyright (C) 2002 David Abrahams +// Copyright (C) 2003 Doug Gregor +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org/libs/bind/ref.html for documentation. +// + +namespace boost +{ + +struct deduce_ref_result {}; + +namespace detail { namespace ref { + +// ------ has_result_type --- +template +type_traits::yes_type has_result_type_helper(type*); + +template type_traits::no_type has_result_type_helper(...); + +template +struct has_result_type +{ + BOOST_STATIC_CONSTANT(bool, + value = (sizeof(has_result_type_helper(0)) + == sizeof(type_traits::yes_type))); +}; + +// ------ has_argument_type --- +template +type_traits::yes_type +has_argument_type_helper(type*); + +template type_traits::no_type has_argument_type_helper(...); + +template +struct has_argument_type +{ + BOOST_STATIC_CONSTANT(bool, + value = (sizeof(has_argument_type_helper(0)) + == sizeof(type_traits::yes_type))); +}; + +// ------ has_first_and_second_argument_types --- +template +type_traits::yes_type has_first_and_second_argument_types_helper( + type*, + type*); + +template +type_traits::no_type has_first_and_second_argument_types_helper(...); + +template +struct has_first_and_second_argument_types +{ + BOOST_STATIC_CONSTANT(bool, + value = (sizeof(has_first_and_second_argument_types_helper(0, 0)) + == sizeof(type_traits::yes_type))); +}; + +// ------ has_argN_type --- +template +struct has_argN_type +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +#define BOOST_REF_HAS_ARGN_TYPE(N) \ +template \ +type_traits::yes_type \ +has_arg##N##_type_helper(type*); \ + \ +template type_traits::no_type has_arg##N##_type_helper(...); \ + \ +template \ +struct has_arg##N##_type \ +{ \ + BOOST_STATIC_CONSTANT(bool, \ + value = (sizeof(has_arg##N##_type_helper(0)) \ + == sizeof(type_traits::yes_type))); \ +}; \ + \ +template \ +struct has_argN_type \ +{ \ + BOOST_STATIC_CONSTANT(bool, value = (has_arg##N##_type::value)); \ +}; + +BOOST_REF_HAS_ARGN_TYPE(1) +BOOST_REF_HAS_ARGN_TYPE(2) +BOOST_REF_HAS_ARGN_TYPE(3) +BOOST_REF_HAS_ARGN_TYPE(4) +BOOST_REF_HAS_ARGN_TYPE(5) +BOOST_REF_HAS_ARGN_TYPE(6) +BOOST_REF_HAS_ARGN_TYPE(7) +BOOST_REF_HAS_ARGN_TYPE(8) +BOOST_REF_HAS_ARGN_TYPE(9) +BOOST_REF_HAS_ARGN_TYPE(10) +#undef BOOST_REF_HAS_ARGN_TYPE + +// ------ get_result_type0 --- +template struct get_result_type0_impl; + +template +struct get_result_type0_impl +{ + typedef typename T::result_type type; +}; + +template +struct get_result_type0_impl +{ + typedef void type; +}; + +template +struct get_result_type0 : + public get_result_type0_impl<(has_result_type::value), T> +{ +}; + +// ------ get_result_type1 --- +template +struct get_result_type1_impl; + +template +struct get_result_type1_impl +{ + typedef typename T::result_type type; +}; + +template +struct get_result_type1_impl +{ + typedef typename T::template sig::type type; +}; + +template +struct get_result_type1 : + public get_result_type1_impl<(has_result_type::value), T, T1> {}; + +// ------ get_result_type2 --- +template +struct get_result_type2_impl; + +template +struct get_result_type2_impl +{ + typedef typename T::result_type type; +}; + +template +struct get_result_type2_impl +{ + typedef typename T::template sig::type type; +}; + +template +struct get_result_type2 : + public get_result_type2_impl<(has_result_type::value), T, T1, T2> {}; + +// ------ get_result_type3 --- +template +struct get_result_type3_impl; + +template +struct get_result_type3_impl +{ + typedef typename T::result_type type; +}; + +template +struct get_result_type3_impl +{ + typedef typename T::template sig::type type; +}; + +template +struct get_result_type3 : + public get_result_type3_impl<(has_result_type::value), T, T1, T2, T3> {}; + +// ------ get_result_type --- +template +struct get_result_type +{ + typedef Result type; +}; + +template +struct get_result_type +{ + typedef typename Deducer::type type; +}; + +// ------ reference_wrapper_base +template +class reference_wrapper_base +{ +public: + operator T& () const { return *(this->t_); } + T& get() const { return *(this->t_); } + T* get_pointer() const { return this->t_; } + + typename get_result_type >::type + operator()() const + { + return get()(); + } + +protected: +#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) + explicit reference_wrapper_base(T& t) : t_(&t) {} +#else + explicit reference_wrapper_base(T& t) : t_(addressof(t)) {} +#endif + +private: + T* t_; +}; + +// ------ reference_wrapper_with_first_and_second_argument_types +template +class reference_wrapper_with_first_and_second_argument_types + : public reference_wrapper_base +{ + typedef reference_wrapper_base inherited; + +protected: + explicit reference_wrapper_with_first_and_second_argument_types(T& t) + : inherited(t) {} + +public: + typedef typename T::first_argument_type first_argument_type; + typedef typename T::second_argument_type second_argument_type; + + using inherited::operator(); + + typename get_result_type >::type + operator()(first_argument_type a1, second_argument_type a2) const + { + return this->get()(a1, a2); + } +}; + +// ------ reference_wrapper_with_argument_type +template +class maybe_also_first_and_second_argument_types; + + +template +class maybe_also_first_and_second_argument_types + : public reference_wrapper_with_first_and_second_argument_types +{ + typedef reference_wrapper_with_first_and_second_argument_types + inherited; + +protected: + explicit maybe_also_first_and_second_argument_types(T& t) : inherited(t) {} + +public: + using inherited::operator(); +}; + +template +class maybe_also_first_and_second_argument_types + : public reference_wrapper_base +{ + typedef reference_wrapper_base inherited; + +protected: + explicit maybe_also_first_and_second_argument_types(T& t) : inherited(t) {} + +public: + using inherited::operator(); +}; + +template +class reference_wrapper_with_argument_type + : public maybe_also_first_and_second_argument_types< + T, Result, + (has_first_and_second_argument_types::value)> +{ + typedef maybe_also_first_and_second_argument_types< + T, Result, + (has_first_and_second_argument_types::value)> inherited; + +protected: + explicit reference_wrapper_with_argument_type(T& t) : inherited(t) {} + +public: + typedef typename T::argument_type argument_type; + + using inherited::operator(); + + typename get_result_type >::type + operator()(argument_type a1) const + { + return this->get()(a1); + } +}; + +// ------ reference_wrapper_with_argN_types +template +class reference_wrapper_with_argN_types_impl; + +template +class reference_wrapper_with_argN_types + : public reference_wrapper_with_argN_types_impl::value)> +{ + typedef reference_wrapper_with_argN_types_impl::value)> + inherited; + +protected: + explicit reference_wrapper_with_argN_types(T& t) : inherited(t) {} +}; + +template +class reference_wrapper_with_argN_types_impl + : public reference_wrapper_with_argN_types +{ + typedef reference_wrapper_with_argN_types inherited; + +protected: + explicit reference_wrapper_with_argN_types_impl(T& t) : inherited(t) {} + +public: + typedef typename T::arg1_type arg1_type; + + using inherited::operator(); + + typename get_result_type >::type + operator()(arg1_type a1) const + { + return this->get()(a1); + } +}; + +template +class reference_wrapper_with_argN_types_impl + : public reference_wrapper_with_argN_types +{ + typedef reference_wrapper_with_argN_types inherited; + +protected: + explicit reference_wrapper_with_argN_types_impl(T& t) : inherited(t) {} + +public: + typedef typename T::arg1_type arg1_type; + typedef typename T::arg2_type arg2_type; + + using inherited::operator(); + + typename get_result_type >::type + operator()(arg1_type a1, arg2_type a2) const + { + return this->get()(a1, a2); + } +}; + +template +class reference_wrapper_with_argN_types_impl + : public reference_wrapper_with_argN_types +{ + typedef reference_wrapper_with_argN_types inherited; + +protected: + explicit reference_wrapper_with_argN_types_impl(T& t) : inherited(t) {} + +public: + typedef typename T::arg1_type arg1_type; + typedef typename T::arg2_type arg2_type; + typedef typename T::arg3_type arg3_type; + + using inherited::operator(); + + typename get_result_type + >::type + operator()(arg1_type a1, arg2_type a2, arg3_type a3) const + { + return this->get()(a1, a2, a3); + } +}; + +// Passed the number of arguments we know how to handle +template +class reference_wrapper_with_argN_types_impl + : public reference_wrapper_base +{ + typedef reference_wrapper_base inherited; + +protected: + explicit reference_wrapper_with_argN_types_impl(T& t) : inherited(t) {} + +public: + using inherited::operator(); +}; + +// Underlying function object does not have any more argument types +template +class reference_wrapper_with_argN_types_impl + : public reference_wrapper_base +{ + typedef reference_wrapper_base inherited; + +protected: + explicit reference_wrapper_with_argN_types_impl(T& t) : inherited(t) {} + +public: + using inherited::operator(); +}; + +// ------ reference_wrapper_with_deduced_args +template +class reference_wrapper_with_deduced_args : + public reference_wrapper_base +{ + typedef reference_wrapper_base inherited; + +protected: + explicit reference_wrapper_with_deduced_args(T& t) : inherited(t) {} + +public: + using inherited::operator(); + + template + typename get_result_type >::type + operator()(T1& a1) const + { return this->get()(a1); } + + template + typename get_result_type >::type + operator()(T1& a1, T2& a2) const + { return this->get()(a1, a2); } + + template + typename get_result_type >::type + operator()(T1& a1, T2& a2, T3& a3) const + { return this->get()(a1, a2, a3); } +}; + +// ------ reference_wrapper_operators +template +class maybe_with_first_and_second_argument_types; + +template +class maybe_with_first_and_second_argument_types + : public reference_wrapper_with_first_and_second_argument_types +{ + typedef reference_wrapper_with_first_and_second_argument_types + inherited; + +protected: + explicit maybe_with_first_and_second_argument_types(T& t) : inherited(t) {} +}; + +template +class maybe_with_first_and_second_argument_types + : public reference_wrapper_with_deduced_args +{ + typedef reference_wrapper_with_deduced_args inherited; + +protected: + explicit maybe_with_first_and_second_argument_types(T& t) : inherited(t) {} +}; + +template +class maybe_with_argument_type; + +template +class maybe_with_argument_type + : public reference_wrapper_with_argument_type +{ + typedef reference_wrapper_with_argument_type inherited; + +protected: + explicit maybe_with_argument_type(T& t) : inherited(t) {} +}; + +template +class maybe_with_argument_type + : public maybe_with_first_and_second_argument_types< + T, Result, + (has_first_and_second_argument_types::value)> +{ + typedef maybe_with_first_and_second_argument_types< + T, Result, + (has_first_and_second_argument_types::value)> + inherited; + +protected: + explicit maybe_with_argument_type(T& t) : inherited(t) {} +}; + +template +class maybe_with_argN_types; + +template +class maybe_with_argN_types + : public reference_wrapper_with_argN_types +{ + typedef reference_wrapper_with_argN_types inherited; + +protected: + explicit maybe_with_argN_types(T& t) : inherited(t) {} +}; + +template +class maybe_with_argN_types + : public maybe_with_argument_type::value)> +{ + typedef maybe_with_argument_type::value)> + inherited; + +protected: + explicit maybe_with_argN_types(T& t) : inherited(t) {} +}; + +template +class reference_wrapper_operators + : public maybe_with_argN_types::value)> +{ + typedef maybe_with_argN_types::value)> + inherited; + +protected: + explicit reference_wrapper_operators(T& t) : inherited(t) {} +}; + +} } // end namespace detail::ref + +template +class reference_wrapper + : public detail::ref::reference_wrapper_operators +{ + typedef detail::ref::reference_wrapper_operators inherited; + +public: + typedef T type; + + explicit reference_wrapper(T& t) : inherited(t) {} +}; + +# if defined(__BORLANDC__) && (__BORLANDC__ <= 0x570) +# define BOOST_REF_CONST +# else +# define BOOST_REF_CONST const +# endif + +template inline reference_wrapper BOOST_REF_CONST ref(T & t) +{ + return reference_wrapper(t); +} + +template inline reference_wrapper BOOST_REF_CONST cref(T const & t) +{ + return reference_wrapper(t); +} + +template +inline reference_wrapper BOOST_REF_CONST ref(T & t) +{ + return reference_wrapper(t); +} + +template +inline reference_wrapper BOOST_REF_CONST cref(T const & t) +{ + return reference_wrapper(t); +} + +# undef BOOST_REF_CONST + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +class is_reference_wrapper +{ + public: + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +class is_reference_wrapper > +{ + public: + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +class unwrap_reference +{ + public: + typedef T type; +}; + +template +class unwrap_reference > +{ + public: + typedef T type; +}; +# else // no partial specialization + +} // namespace boost + +namespace boost +{ + +namespace detail +{ + typedef char (&yes_reference_wrapper_t)[1]; + typedef char (&no_reference_wrapper_t)[2]; + + no_reference_wrapper_t is_reference_wrapper_test(...); + + template + yes_reference_wrapper_t + is_reference_wrapper_test(type< reference_wrapper >); + + template + struct reference_unwrapper + { + template + struct apply + { + typedef T type; + }; + }; + + template<> + struct reference_unwrapper + { + template + struct apply + { + typedef typename T::type type; + }; + }; +} + +template +class is_reference_wrapper +{ + public: + BOOST_STATIC_CONSTANT( + bool, value = ( + sizeof(detail::is_reference_wrapper_test(type())) + == sizeof(detail::yes_reference_wrapper_t))); +}; + +template +class unwrap_reference + : public detail::reference_unwrapper< + is_reference_wrapper::value + >::template apply +{}; + +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +} // namespace boost + +#endif // #ifndef BOOST_REF_HPP_INCLUDED diff --git a/ref_call_test.cpp b/ref_call_test.cpp new file mode 100644 index 0000000..544fccd --- /dev/null +++ b/ref_call_test.cpp @@ -0,0 +1,540 @@ +#include +#include +#include +#include +#include + +class generate_zero { +public: + typedef int result_type; + generate_zero() {} + int operator()() const { return 0; } + +private: + generate_zero(const generate_zero&); +}; + +class generate_zero_no_result_type { +public: + generate_zero_no_result_type() {} + int operator()() const { return 0; } + +private: + generate_zero_no_result_type(const generate_zero_no_result_type&); +}; + +template +void check_generate_zero(F f) +{ + assert(f() == 0); +} + +class negate_with_arg_type +{ +public: + typedef int result_type; + typedef int argument_type; + + negate_with_arg_type() {} + int operator()(int x) const { return -x; } + +private: + negate_with_arg_type(const negate_with_arg_type&); +}; + +class negate_with_arg1_type +{ +public: + typedef int result_type; + typedef int arg1_type; + + negate_with_arg1_type() {} + int operator()(int x) const { return -x; } + +private: + negate_with_arg1_type(const negate_with_arg1_type&); +}; + +class negate_with_no_arg +{ +public: + typedef int result_type; + + negate_with_no_arg() {} + int operator()(int x) const { return -x; } + +private: + negate_with_no_arg(const negate_with_no_arg&); +}; + +class negate_with_arg_type_sig +{ +public: + template + struct sig + { + typedef int type; + }; + + typedef int argument_type; + + negate_with_arg_type_sig() {} + int operator()(int x) const { return -x; } + +private: + negate_with_arg_type_sig(const negate_with_arg_type_sig&); +}; + +class negate_with_arg1_type_sig +{ +public: + template + struct sig + { + typedef int type; + }; + + typedef int arg1_type; + + negate_with_arg1_type_sig() {} + int operator()(int x) const { return -x; } + +private: + negate_with_arg1_type_sig(const negate_with_arg1_type_sig&); +}; + +class negate_with_no_arg_sig +{ +public: + template + struct sig + { + typedef int type; + }; + + negate_with_no_arg_sig() {} + int operator()(int x) const { return -x; } + +private: + negate_with_no_arg_sig(const negate_with_no_arg_sig&); +}; + +class negate_with_arg_type_nrt +{ +public: + typedef int argument_type; + + negate_with_arg_type_nrt() {} + int operator()(int x) const { return -x; } + +private: + negate_with_arg_type_nrt(const negate_with_arg_type_nrt&); +}; + +class negate_with_arg1_type_nrt +{ +public: + typedef int arg1_type; + + negate_with_arg1_type_nrt() {} + int operator()(int x) const { return -x; } + +private: + negate_with_arg1_type_nrt(const negate_with_arg1_type_nrt&); +}; + +class negate_with_no_arg_nrt +{ +public: + negate_with_no_arg_nrt() {} + int operator()(int x) const { return -x; } + +private: + negate_with_no_arg_nrt(const negate_with_no_arg_nrt&); +}; + +template +void check_negate(F f) +{ + assert(f(5) == -5); +} + +template +void check_negate_deduced(F f) +{ + int x = 5; + assert(f(x) == -x); +} + +class add_with_fs_arg_types +{ +public: + typedef int result_type; + typedef int first_argument_type; + typedef int second_argument_type; + + add_with_fs_arg_types() {} + int operator()(int x, int y) const { return x + y; } + +private: + add_with_fs_arg_types(const add_with_fs_arg_types&); +}; + +class add_with_argN_types +{ +public: + typedef int result_type; + typedef int arg1_type; + typedef int arg2_type; + + add_with_argN_types() {} + int operator()(int x, int y) const { return x + y; } + +private: + add_with_argN_types(const add_with_argN_types&); +}; + +class add_with_no_args +{ +public: + typedef int result_type; + + add_with_no_args() {} + int operator()(int x, int y) const { return x + y; } + +private: + add_with_no_args(const add_with_no_args&); +}; + +class add_with_fs_arg_types_sig +{ +public: + template struct sig { typedef int type; }; + typedef int first_argument_type; + typedef int second_argument_type; + + add_with_fs_arg_types_sig() {} + int operator()(int x, int y) const { return x + y; } + +private: + add_with_fs_arg_types_sig(const add_with_fs_arg_types_sig&); +}; + +class add_with_argN_types_sig +{ +public: + template struct sig { typedef int type; }; + typedef int arg1_type; + typedef int arg2_type; + + add_with_argN_types_sig() {} + int operator()(int x, int y) const { return x + y; } + +private: + add_with_argN_types_sig(const add_with_argN_types_sig&); +}; + +class add_with_no_args_sig +{ +public: + template struct sig { typedef int type; }; + + add_with_no_args_sig() {} + int operator()(int x, int y) const { return x + y; } + +private: + add_with_no_args_sig(const add_with_no_args_sig&); +}; + +class add_with_fs_arg_types_nrt +{ +public: + typedef int first_argument_type; + typedef int second_argument_type; + + add_with_fs_arg_types_nrt() {} + int operator()(int x, int y) const { return x + y; } + +private: + add_with_fs_arg_types_nrt(const add_with_fs_arg_types_nrt&); +}; + +class add_with_argN_types_nrt +{ +public: + typedef int arg1_type; + typedef int arg2_type; + + add_with_argN_types_nrt() {} + int operator()(int x, int y) const { return x + y; } + +private: + add_with_argN_types_nrt(const add_with_argN_types_nrt&); +}; + +class add_with_no_args_nrt +{ +public: + add_with_no_args_nrt() {} + int operator()(int x, int y) const { return x + y; } + +private: + add_with_no_args_nrt(const add_with_no_args&); +}; + +template +void check_sum(F f) +{ + assert(f(3, 5) == 8); +} + +template +void check_sum_deduced(F f) +{ + int x = 3; + int y = 5; + assert(f(x, y) == x+y); +} + +struct zero_negate_add_fs_arg_types +{ +public: + typedef int result_type; + typedef int argument_type; + typedef int first_argument_type; + typedef int second_argument_type; + + zero_negate_add_fs_arg_types() {} + int operator()() const { return 0; } + int operator()(int x) const { return -x; } + int operator()(int x, int y) const { return x+y; } + +private: + zero_negate_add_fs_arg_types(const zero_negate_add_fs_arg_types&); +}; + +struct zero_negate_add_argN_types +{ +public: + typedef int result_type; + typedef int arg1_type; + typedef int arg2_type; + + zero_negate_add_argN_types() {} + int operator()() const { return 0; } + int operator()(int x) const { return -x; } + int operator()(int x, int y) const { return x+y; } + +private: + zero_negate_add_argN_types(const zero_negate_add_argN_types&); +}; + +struct zero_negate_add_no_arg +{ +public: + typedef int result_type; + + zero_negate_add_no_arg() {} + int operator()() const { return 0; } + int operator()(int x) const { return -x; } + int operator()(int x, int y) const { return x+y; } + +private: + zero_negate_add_no_arg(const zero_negate_add_no_arg&); +}; + +struct zero_negate_add_fs_arg_types_sig +{ +public: + template + struct sig + { + typedef int type; + }; + + typedef int argument_type; + typedef int first_argument_type; + typedef int second_argument_type; + + zero_negate_add_fs_arg_types_sig() {} + int operator()() const { return 0; } + int operator()(int x) const { return -x; } + int operator()(int x, int y) const { return x+y; } + +private: + zero_negate_add_fs_arg_types_sig(const zero_negate_add_fs_arg_types_sig&); +}; + +struct zero_negate_add_argN_types_sig +{ +public: + template + struct sig + { + typedef int type; + }; + + typedef int arg1_type; + typedef int arg2_type; + + zero_negate_add_argN_types_sig() {} + int operator()() const { return 0; } + int operator()(int x) const { return -x; } + int operator()(int x, int y) const { return x+y; } + +private: + zero_negate_add_argN_types_sig(const zero_negate_add_argN_types_sig&); +}; + +struct zero_negate_add_no_arg_sig +{ +public: + template + struct sig + { + typedef int type; + }; + + zero_negate_add_no_arg_sig() {} + int operator()() const { return 0; } + int operator()(int x) const { return -x; } + int operator()(int x, int y) const { return x+y; } + +private: + zero_negate_add_no_arg_sig(const zero_negate_add_no_arg_sig&); +}; + + +struct zero_negate_add_fs_arg_types_nrt +{ +public: + typedef int argument_type; + typedef int first_argument_type; + typedef int second_argument_type; + + zero_negate_add_fs_arg_types_nrt() {} + int operator()() const { return 0; } + int operator()(int x) const { return -x; } + int operator()(int x, int y) const { return x+y; } + +private: + zero_negate_add_fs_arg_types_nrt(const zero_negate_add_fs_arg_types_nrt&); +}; + +struct zero_negate_add_argN_types_nrt +{ +public: + typedef int arg1_type; + typedef int arg2_type; + + zero_negate_add_argN_types_nrt() {} + int operator()() const { return 0; } + int operator()(int x) const { return -x; } + int operator()(int x, int y) const { return x+y; } + +private: + zero_negate_add_argN_types_nrt(const zero_negate_add_argN_types_nrt&); +}; + +struct zero_negate_add_no_arg_nrt +{ +public: + zero_negate_add_no_arg_nrt() {} + int operator()() const { return 0; } + int operator()(int x) const { return -x; } + int operator()(int x, int y) const { return x+y; } + +private: + zero_negate_add_no_arg_nrt(const zero_negate_add_no_arg_nrt&); +}; + +int main() +{ + // Arity zero function objects + generate_zero gz; + generate_zero_no_result_type gznrt; + check_generate_zero(boost::ref(gz)); + check_generate_zero(boost::ref(gznrt)); + + // Arity 1 function objects + negate_with_arg_type na; + negate_with_arg1_type na1; + negate_with_no_arg nn; + negate_with_arg_type_sig nas; + negate_with_arg1_type_sig na1s; + negate_with_no_arg_sig nns; + negate_with_arg_type_nrt nanrt; + negate_with_arg1_type_nrt na1nrt; + negate_with_no_arg_nrt nnnrt; + check_negate(boost::ref(na)); + check_negate(boost::ref(na1)); + check_negate_deduced(boost::ref(nn)); + check_negate(boost::ref(nas)); + check_negate(boost::ref(na1s)); + check_negate_deduced(boost::ref(nns)); + check_negate(boost::ref(nanrt)); + check_negate(boost::ref(na1nrt)); + check_negate_deduced(boost::ref(nnnrt)); + + // Arity 2 function objects + add_with_fs_arg_types aa; + add_with_fs_arg_types a2; + add_with_no_args an; + add_with_fs_arg_types_sig aas; + add_with_fs_arg_types_sig a2s; + add_with_no_args_sig ans; + add_with_fs_arg_types_nrt aanrt; + add_with_fs_arg_types_nrt a2nrt; + add_with_no_args_nrt annrt; + check_sum(boost::ref(aa)); + check_sum(boost::ref(a2)); + check_sum_deduced(boost::ref(an)); + check_sum(boost::ref(aas)); + check_sum(boost::ref(a2s)); + check_sum_deduced(boost::ref(ans)); + check_sum(boost::ref(aanrt)); + check_sum(boost::ref(a2nrt)); + check_sum_deduced(boost::ref(annrt)); + + // Arity overloading in function objects + zero_negate_add_argN_types znaa; + zero_negate_add_fs_arg_types znafs; + zero_negate_add_no_arg znana; + check_generate_zero(boost::ref(znaa)); + check_negate(boost::ref(znaa)); + check_sum(boost::ref(znaa)); + check_generate_zero(boost::ref(znafs)); + check_negate(boost::ref(znafs)); + check_sum(boost::ref(znafs)); + check_generate_zero(boost::ref(znana)); + check_negate_deduced(boost::ref(znana)); + check_sum_deduced(boost::ref(znana)); + + zero_negate_add_argN_types_sig znaas; + zero_negate_add_fs_arg_types_sig znafss; + zero_negate_add_no_arg_sig znanas; + // check_generate_zero(boost::ref(znaas)); + check_negate(boost::ref(znaas)); + check_sum(boost::ref(znaas)); + // check_generate_zero(boost::ref(znafss)); + check_negate(boost::ref(znafss)); + check_sum(boost::ref(znafss)); + // check_generate_zero(boost::ref(znanas)); + check_negate_deduced(boost::ref(znanas)); + check_sum_deduced(boost::ref(znanas)); + + zero_negate_add_argN_types znaanrt; + zero_negate_add_fs_arg_types znafsnrt; + zero_negate_add_no_arg znananrt; + check_generate_zero(boost::ref(znaanrt)); + check_negate(boost::ref(znaanrt)); + check_sum(boost::ref(znaanrt)); + check_generate_zero(boost::ref(znafsnrt)); + check_negate(boost::ref(znafsnrt)); + check_sum(boost::ref(znafsnrt)); + check_generate_zero(boost::ref(znananrt)); + check_negate_deduced(boost::ref(znananrt)); + check_sum_deduced(boost::ref(znananrt)); + + return 0; +}