Squashed 'third_party/boostorg/function_types/' content from commit ae4fde2

Change-Id: I946aaade9862a3a50fdce89fbc618c914b0edae6
git-subtree-dir: third_party/boostorg/function_types
git-subtree-split: ae4fde2e2ae88291d6d656137169ff4003d184a1
diff --git a/example/fast_mem_fn.hpp b/example/fast_mem_fn.hpp
new file mode 100644
index 0000000..2587c18
--- /dev/null
+++ b/example/fast_mem_fn.hpp
@@ -0,0 +1,248 @@
+
+// (C) Copyright Tobias Schwinger
+//
+// Use modification and distribution are subject to the boost Software License,
+// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt).
+
+//------------------------------------------------------------------------------
+//
+// This example implements a very efficient, generic member function wrapper.
+//
+//
+// Detailed description
+// ====================
+//
+// For most platforms C++ runs on (maybe all hardware platforms, as opposed to
+// virtual machines) there are indirect calls that take more time to execute 
+// than direct ones. Further calling a function usually takes more time than 
+// inlining it at the call site.
+//
+// A direct call is a machine instruction that calls a subroutine at a known
+// address encoded in the instruction itself. C++ compilers usually emit one of
+// these instructions for each function call to a nonvirtual function (a call to
+// a virtual function requires either two direct calls or one indirect call).
+// An indirect call is a machine instruction that calls a subroutine at an 
+// address known at runtime. C++ compilers usually emit at least one of these 
+// instructions for a call through a callable builtin variable.
+//
+// It is possible to use callable scalars as non-type template arguments. This
+// way the compiler knows which function we want to call when generating the
+// code for the call site, so it may inline (if it decides to do so) or use a 
+// direct call instead of being forced to use a slow, indirect call.
+//
+// We define a functor class template that encodes the function to call in its
+// type via a non-type template argument. Its (inline declared) overloaded 
+// function call operator calls the function through that non-type template 
+// argument. In the best case we end up inlining the callee directly at the
+// point of the call.
+//
+// Decomposition of the wrapped member function's type is needed in order to 
+// implement argument forwarding (just using a templated call operator we would 
+// encounter what is known as "the forwarding problem" [Dimov1]). Further we
+// can eliminate unecessary copies for each by-value parameter by using a 
+// reference to its const qualified type for the corresponding parameter of the
+// wrapper's function call operator.
+//
+// Finally we provide a macro that does have similar semantics to the function 
+// template mem_fn of the Bind [2] library.
+// We can't use a function template and use a macro instead, because we use a
+// member function pointer that is a compile time constant. So we first have to
+// deduce the type and create a template that accepts this type as a non-type 
+// template argument, which is passed in in a second step. The macro hides this
+// lengthy expression from the user.
+//
+//
+// Limitations
+// ===========
+//
+// The "this-argument" must be specified as a reference.
+//
+//
+// Bibliography
+// ============
+//
+// [Dimov1] Dimov, P., Hinnant H., Abrahams, D. The Forwarding Problem
+//          http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm
+//
+// [Dimov2] Dimov, P. Documentation of boost::mem_fn
+//          http://www.boost.org/libs/bind/mem_fn.html
+
+#ifndef BOOST_EXAMPLE_FAST_MEM_FN_HPP_INCLUDED
+#ifndef BOOST_PP_IS_ITERATING
+
+
+#include <boost/function_types/result_type.hpp>
+#include <boost/function_types/function_arity.hpp>
+#include <boost/function_types/parameter_types.hpp>
+#include <boost/function_types/is_member_function_pointer.hpp>
+
+#include <boost/mpl/transform_view.hpp>
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/deref.hpp>
+
+#include <boost/utility/enable_if.hpp>
+
+#include "detail/param_type.hpp"
+
+namespace example
+{
+
+  namespace ft = boost::function_types;
+  namespace mpl = boost::mpl;
+  using namespace mpl::placeholders;
+
+  // the functor class template
+  template< typename MFPT, MFPT MemberFunction
+    , size_t Arity = ::example::ft::function_arity<MFPT>::value
+  >
+  struct fast_mem_fn;
+
+  // ------- ---- --- -- - - - -
+
+  // deduce type and capture compile time value 
+  #define BOOST_EXAMPLE_FAST_MEM_FN(mfp) \
+      ::example::make_fast_mem_fn(mfp).make_fast_mem_fn<mfp>()
+
+  template<typename MFPT>
+  struct fast_mem_fn_maker
+  {
+    template<MFPT Callee>
+    fast_mem_fn<MFPT,Callee> make_fast_mem_fn()
+    {
+      return fast_mem_fn<MFPT,Callee>();
+    } 
+  };
+
+  template<typename MFPT>
+      typename boost::enable_if<boost::is_member_function_pointer<MFPT>, 
+  fast_mem_fn_maker<MFPT>                                                >::type
+  make_fast_mem_fn(MFPT)
+  {
+    return fast_mem_fn_maker<MFPT>();
+  }
+
+
+  // ------- ---- --- -- - - - -
+
+  namespace detail
+  {
+    // by-value forwarding optimization
+    template<typename T>
+    struct parameter_types
+      : mpl::transform_view<ft::parameter_types<T>,param_type<_> >
+    { }; 
+  }
+
+  // ------- ---- --- -- - - - -
+
+  template< typename MFPT, MFPT MemberFunction >
+  struct fast_mem_fn<MFPT, MemberFunction, 1>
+  {
+    // decompose the result and the parameter types (public for introspection)
+    typedef typename ft::result_type<MFPT>::type result_type;
+    typedef detail::parameter_types<MFPT> parameter_types;
+  private:
+    // iterate the parameter types 
+    typedef typename mpl::begin<parameter_types>::type i0;
+  public: 
+    // forwarding function call operator
+    result_type operator()( typename mpl::deref<i0>::type a0) const
+    {
+      return (a0.*MemberFunction)();
+    };
+  };
+
+  template< typename MFPT, MFPT MemberFunction >
+  struct fast_mem_fn<MFPT, MemberFunction, 2>
+  {
+    // decompose the result and the parameter types (public for introspection)
+    typedef typename ft::result_type<MFPT>::type result_type;
+    typedef detail::parameter_types<MFPT> parameter_types;
+  private:
+    // iterate the parameter types 
+    typedef typename mpl::begin<parameter_types>::type i0;
+    typedef typename mpl::next<i0>::type i1;
+  public: 
+    // forwarding function call operator
+    result_type operator()( typename mpl::deref<i0>::type a0
+                          , typename mpl::deref<i1>::type a1) const
+    {
+      return (a0.*MemberFunction)(a1);
+    };
+  };
+
+  template< typename MFPT, MFPT MemberFunction >
+  struct fast_mem_fn<MFPT, MemberFunction, 3>
+  {
+    // decompose the result and the parameter types (public for introspection)
+    typedef typename ft::result_type<MFPT>::type result_type;
+    typedef detail::parameter_types<MFPT> parameter_types;
+  private:
+    // iterate the parameter types 
+    typedef typename mpl::begin<parameter_types>::type i0;
+    typedef typename mpl::next<i0>::type i1;
+    typedef typename mpl::next<i1>::type i2;
+  public: 
+    // forwarding function call operator
+    result_type operator()( typename mpl::deref<i0>::type a0
+                          , typename mpl::deref<i1>::type a1
+                          , typename mpl::deref<i2>::type a2) const
+    {
+      return (a0.*MemberFunction)(a1,a2);
+    };
+  };
+
+  // ...
+}
+
+// ------- ---- --- -- - - - -
+
+// preprocessor-based code generator to continue the repetitive part, above
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/iteration/iterate.hpp>
+#include <boost/preprocessor/iteration/local.hpp>
+#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+
+namespace example
+{
+  #if BOOST_FT_MAX_ARITY >= 4
+  #   define  BOOST_PP_FILENAME_1 "fast_mem_fn.hpp"
+  #   define  BOOST_PP_ITERATION_LIMITS (4,BOOST_FT_MAX_ARITY)
+  #   include BOOST_PP_ITERATE()
+  #endif
+}
+
+#define BOOST_EXAMPLE_FAST_MEM_FN_HPP_INCLUDED
+#else
+
+  #define N BOOST_PP_FRAME_ITERATION(1)
+  template< typename MFPT, MFPT MemberFunction >
+  struct fast_mem_fn<MFPT, MemberFunction, N >
+  {
+    // decompose the result and the parameter types (public for introspection)
+    typedef typename ft::result_type<MFPT>::type result_type;
+    typedef detail::parameter_types<MFPT> parameter_types;
+  private:
+    // iterate the parameter types 
+    typedef typename mpl::begin<parameter_types>::type i0;
+    #define  BOOST_PP_LOCAL_LIMITS (0,N-2)
+    #define  BOOST_PP_LOCAL_MACRO(j) \
+    typedef typename mpl::next< i ## j >::type BOOST_PP_CAT(i,BOOST_PP_INC(j)) ;
+    #include BOOST_PP_LOCAL_ITERATE()
+  public: 
+    // forwarding function call operator
+    result_type operator()( 
+        BOOST_PP_ENUM_BINARY_PARAMS(N, typename mpl::deref<i,>::type a) )  const
+    {
+      return (a0.*MemberFunction)(BOOST_PP_ENUM_SHIFTED_PARAMS(N,a));
+    };
+  };
+  #undef N
+
+#endif
+#endif
+