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/interpreter.hpp b/example/interpreter.hpp
new file mode 100644
index 0000000..72cd78b
--- /dev/null
+++ b/example/interpreter.hpp
@@ -0,0 +1,189 @@
+
+// (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 simple batch-style interpreter that is capable of
+// calling functions previously registered with it. The parameter types of the
+// functions are used to control the parsing of the input.
+//
+// Implementation description
+// ==========================
+//
+// When a function is registered, an 'invoker' template is instantiated with
+// the function's type. The 'invoker' fetches a value from the 'token_parser'
+// for each parameter of the function into a tuple and finally invokes the the
+// function with these values as arguments. The invoker's entrypoint, which
+// is a function of the callable builtin that describes the function to call and
+// a reference to the 'token_parser', is partially bound to the registered
+// function and put into a map so it can be found by name during parsing.
+
+#include <map>
+#include <string>
+#include <stdexcept>
+
+#include <boost/token_iterator.hpp>
+#include <boost/token_functions.hpp>
+
+#include <boost/lexical_cast.hpp>
+
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+#include <boost/fusion/include/push_back.hpp>
+#include <boost/fusion/include/cons.hpp>
+#include <boost/fusion/include/invoke.hpp>
+
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/end.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/deref.hpp>
+
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/function_types/is_nonmember_callable_builtin.hpp>
+#include <boost/function_types/parameter_types.hpp>
+
+namespace example
+{
+  namespace fusion = boost::fusion;
+  namespace ft = boost::function_types;
+  namespace mpl = boost::mpl;
+
+  class interpreter
+  {
+    class token_parser;
+    typedef boost::function<void(token_parser &)> invoker_function;
+    typedef std::map<std::string, invoker_function> dictionary;
+
+    dictionary map_invokers;
+  public:
+    // Registers a function with the interpreter.
+    template<typename Function>
+    typename boost::enable_if< ft::is_nonmember_callable_builtin<Function>
+    >::type register_function(std::string const & name, Function f);
+
+    // Parse input for functions to call.
+    void parse_input(std::string const & text) const;
+
+  private:
+    template< typename Function
+    , class From = typename mpl::begin< ft::parameter_types<Function> >::type
+    , class To   = typename mpl::end< ft::parameter_types<Function> >::type
+    >
+    struct invoker;
+  };
+
+  class interpreter::token_parser
+  {
+    typedef boost::token_iterator_generator<
+        boost::char_separator<char> >::type token_iterator;
+
+    token_iterator itr_at, itr_to;
+  public:
+
+    token_parser(token_iterator from, token_iterator to)
+      : itr_at(from), itr_to(to)
+    { }
+
+  private:
+    template<typename T>
+    struct remove_cv_ref
+      : boost::remove_cv< typename boost::remove_reference<T>::type >
+    { };
+  public:
+    // Returns a token of given type.
+    // We just apply boost::lexical_cast to whitespace separated string tokens
+    // for simplicity.
+    template<typename RequestedType>
+    typename remove_cv_ref<RequestedType>::type get()
+    {
+      if (! this->has_more_tokens())
+        throw std::runtime_error("unexpected end of input");
+
+      try
+      {
+        typedef typename remove_cv_ref<RequestedType>::type result_type;
+        result_type result = boost::lexical_cast
+            <typename remove_cv_ref<result_type>::type>(*this->itr_at);
+        ++this->itr_at;
+        return result;
+      }
+
+      catch (boost::bad_lexical_cast &)
+      { throw std::runtime_error("invalid argument: " + *this->itr_at); }
+    }
+
+    // Any more tokens?
+    bool has_more_tokens() const { return this->itr_at != this->itr_to; }
+  };
+
+  template<typename Function, class From, class To>
+  struct interpreter::invoker
+  {
+    // add an argument to a Fusion cons-list for each parameter type
+    template<typename Args>
+    static inline
+    void apply(Function func, token_parser & parser, Args const & args)
+    {
+      typedef typename mpl::deref<From>::type arg_type;
+      typedef typename mpl::next<From>::type next_iter_type;
+
+      interpreter::invoker<Function, next_iter_type, To>::apply
+          ( func, parser, fusion::push_back(args, parser.get<arg_type>()) );
+    }
+  };
+
+  template<typename Function, class To>
+  struct interpreter::invoker<Function,To,To>
+  {
+    // the argument list is complete, now call the function
+    template<typename Args>
+    static inline
+    void apply(Function func, token_parser &, Args const & args)
+    {
+      fusion::invoke(func,args);
+    }
+  };
+
+  template<typename Function>
+  typename boost::enable_if< ft::is_nonmember_callable_builtin<Function> >::type
+  interpreter::register_function(std::string const & name, Function f)
+  {
+    // instantiate and store the invoker by name
+    this->map_invokers[name] = boost::bind(
+        & invoker<Function>::template apply<fusion::nil>, f,_1,fusion::nil() );
+  }
+
+
+  void interpreter::parse_input(std::string const & text) const
+  {
+    boost::char_separator<char> s(" \t\n\r");
+
+    token_parser parser
+      ( boost::make_token_iterator<std::string>(text.begin(), text.end(), s)
+      , boost::make_token_iterator<std::string>(text.end()  , text.end(), s) );
+
+    while (parser.has_more_tokens())
+    {
+      // read function name
+      std::string func_name = parser.get<std::string>();
+
+      // look up function
+      dictionary::const_iterator entry = map_invokers.find( func_name );
+      if (entry == map_invokers.end())
+        throw std::runtime_error("unknown function: " + func_name);
+
+      // call the invoker which controls argument parsing
+      entry->second(parser);
+    }
+  }
+
+}
+