summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/function_types
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/function_types
parentInitial commit. (diff)
downloadceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.tar.xz
ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.zip
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/function_types')
-rw-r--r--src/boost/libs/function_types/CMakeLists.txt25
-rw-r--r--src/boost/libs/function_types/build/Jamfile30
-rw-r--r--src/boost/libs/function_types/build/preprocess_arity_loops.cpp88
-rw-r--r--src/boost/libs/function_types/build/preprocess_cc_names.cpp27
-rw-r--r--src/boost/libs/function_types/build/preprocess_encoding.cpp45
-rw-r--r--src/boost/libs/function_types/build/timestamps/arity_loops1
-rw-r--r--src/boost/libs/function_types/build/timestamps/cc_names1
-rw-r--r--src/boost/libs/function_types/build/timestamps/encoding1
-rw-r--r--src/boost/libs/function_types/example/Jamfile20
-rw-r--r--src/boost/libs/function_types/example/detail/param_type.hpp71
-rw-r--r--src/boost/libs/function_types/example/fast_mem_fn.hpp248
-rw-r--r--src/boost/libs/function_types/example/fast_mem_fn_example.cpp122
-rw-r--r--src/boost/libs/function_types/example/interface.hpp361
-rw-r--r--src/boost/libs/function_types/example/interface_example.cpp80
-rw-r--r--src/boost/libs/function_types/example/interpreter.hpp189
-rw-r--r--src/boost/libs/function_types/example/interpreter_example.cpp56
-rw-r--r--src/boost/libs/function_types/example/macro_type_args.hpp73
-rw-r--r--src/boost/libs/function_types/example/macro_type_args_example.cpp71
-rw-r--r--src/boost/libs/function_types/example/result_of.hpp86
-rw-r--r--src/boost/libs/function_types/example/result_of_example.cpp59
-rw-r--r--src/boost/libs/function_types/index.html14
-rw-r--r--src/boost/libs/function_types/meta/libraries.json15
-rw-r--r--src/boost/libs/function_types/test/Jamfile89
-rw-r--r--src/boost/libs/function_types/test/classification/is_callable_builtin.cpp86
-rw-r--r--src/boost/libs/function_types/test/classification/is_cv_function.cpp142
-rw-r--r--src/boost/libs/function_types/test/classification/is_cv_mem_func_ptr.cpp150
-rw-r--r--src/boost/libs/function_types/test/classification/is_cv_pointer.cpp50
-rw-r--r--src/boost/libs/function_types/test/classification/is_function.cpp87
-rw-r--r--src/boost/libs/function_types/test/classification/is_function_pointer.cpp87
-rw-r--r--src/boost/libs/function_types/test/classification/is_function_reference.cpp88
-rw-r--r--src/boost/libs/function_types/test/classification/is_member_function_pointer.cpp96
-rw-r--r--src/boost/libs/function_types/test/classification/is_member_object_pointer.cpp95
-rw-r--r--src/boost/libs/function_types/test/classification/is_member_pointer.cpp88
-rw-r--r--src/boost/libs/function_types/test/classification/is_nonmember_callable_builtin.cpp87
-rw-r--r--src/boost/libs/function_types/test/classification/is_variadic.cpp143
-rw-r--r--src/boost/libs/function_types/test/custom_ccs/member_ccs.cpp50
-rw-r--r--src/boost/libs/function_types/test/custom_ccs/member_ccs_exact.cpp71
-rw-r--r--src/boost/libs/function_types/test/custom_ccs/nonmember_ccs.cpp45
-rw-r--r--src/boost/libs/function_types/test/custom_ccs/nonmember_ccs_exact.cpp62
-rw-r--r--src/boost/libs/function_types/test/custom_ccs/property_tag.cpp64
-rw-r--r--src/boost/libs/function_types/test/decomposition/class_type_transform.cpp62
-rw-r--r--src/boost/libs/function_types/test/decomposition/components.cpp59
-rw-r--r--src/boost/libs/function_types/test/decomposition/components_seq.cpp75
-rw-r--r--src/boost/libs/function_types/test/decomposition/function_arity.cpp31
-rw-r--r--src/boost/libs/function_types/test/decomposition/function_arity_fail.cpp19
-rw-r--r--src/boost/libs/function_types/test/decomposition/parameter_types.cpp59
-rw-r--r--src/boost/libs/function_types/test/decomposition/parameter_types_fail.cpp19
-rw-r--r--src/boost/libs/function_types/test/decomposition/result_type.cpp98
-rw-r--r--src/boost/libs/function_types/test/decomposition/result_type_fail.cpp19
-rw-r--r--src/boost/libs/function_types/test/reconfiguration/cc_preprocessing.cpp11
-rw-r--r--src/boost/libs/function_types/test/reconfiguration/partial_arity_preprocessing.cpp11
-rw-r--r--src/boost/libs/function_types/test/reconfiguration/preprocessing_mode.cpp11
-rw-r--r--src/boost/libs/function_types/test/reconfiguration/simple_test.hpp51
-rw-r--r--src/boost/libs/function_types/test/synthesis/cv_function_synthesis.cpp249
-rw-r--r--src/boost/libs/function_types/test/synthesis/function_pointer.cpp24
-rw-r--r--src/boost/libs/function_types/test/synthesis/function_reference.cpp24
-rw-r--r--src/boost/libs/function_types/test/synthesis/function_type.cpp23
-rw-r--r--src/boost/libs/function_types/test/synthesis/mem_func_ptr_cv1.cpp94
-rw-r--r--src/boost/libs/function_types/test/synthesis/mem_func_ptr_cv2.cpp94
-rw-r--r--src/boost/libs/function_types/test/synthesis/mem_func_ptr_cv_ptr_to_this.cpp37
-rw-r--r--src/boost/libs/function_types/test/synthesis/member_function_pointer.cpp66
-rw-r--r--src/boost/libs/function_types/test/synthesis/member_object_pointer.cpp27
-rw-r--r--src/boost/libs/function_types/test/synthesis/transformation.cpp75
-rw-r--r--src/boost/libs/function_types/test/synthesis/variadic_function_synthesis.cpp63
64 files changed, 4564 insertions, 0 deletions
diff --git a/src/boost/libs/function_types/CMakeLists.txt b/src/boost/libs/function_types/CMakeLists.txt
new file mode 100644
index 000000000..705a7bb9e
--- /dev/null
+++ b/src/boost/libs/function_types/CMakeLists.txt
@@ -0,0 +1,25 @@
+# Copyright 2019 Mike Dev
+# Distributed under the Boost Software License, Version 1.0.
+# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
+#
+# NOTE: CMake support for Boost.FunctionTypes is currently experimental at best
+# and the interface is likely to change in the future
+
+cmake_minimum_required( VERSION 3.5 )
+project( BoostFunctionTypes LANGUAGES CXX )
+
+add_library( boost_function_types INTERFACE )
+add_library( Boost::function_types ALIAS boost_function_types )
+
+target_include_directories( boost_function_types INTERFACE include )
+
+target_link_libraries( boost_function_types
+ INTERFACE
+ Boost::config
+ Boost::core
+ Boost::detail
+ Boost::mpl
+ Boost::preprocessor
+ Boost::type_traits
+)
+
diff --git a/src/boost/libs/function_types/build/Jamfile b/src/boost/libs/function_types/build/Jamfile
new file mode 100644
index 000000000..38b185a22
--- /dev/null
+++ b/src/boost/libs/function_types/build/Jamfile
@@ -0,0 +1,30 @@
+
+# (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).
+
+# Generates preprocessed files with wave.
+
+actions wave
+{
+ $(>[1]) -S../../.. $(>[2]) -o $(<)
+}
+
+W = ../../../tools/wave/build//wave ;
+
+make arity_loops
+ : preprocess_arity_loops.cpp $(W) : wave : <location>build/timestamps
+ ;
+
+make encoding
+ : preprocess_encoding.cpp $(W) : wave : <location>build/timestamps
+ ;
+
+
+make cc_names
+ : preprocess_cc_names.cpp $(W) : wave : <location>build/timestamps
+ ;
+
+explicit arity_loops encoding cc_names ;
+
diff --git a/src/boost/libs/function_types/build/preprocess_arity_loops.cpp b/src/boost/libs/function_types/build/preprocess_arity_loops.cpp
new file mode 100644
index 000000000..d39b65cf6
--- /dev/null
+++ b/src/boost/libs/function_types/build/preprocess_arity_loops.cpp
@@ -0,0 +1,88 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#if !defined(BOOST_FT_PREPROCESSING_MODE)
+
+# ifndef __WAVE__
+# error "Boost.Wave preprocessor required"
+# endif
+
+# include <boost/preprocessor/seq/cat.hpp>
+# include <boost/preprocessor/stringize.hpp>
+
+# if BOOST_PP_NIL // enable dependency scanning for dynamically included files
+# include <boost/function_types/detail/encoding/def.hpp>
+# include <boost/function_types/detail/components_impl/master.hpp>
+# include <boost/function_types/detail/synthesize_impl/master.hpp>
+# include <boost/function_types/detail/classifier_impl/master.hpp>
+# endif
+
+# pragma wave option(line: 0, preserve: 2)
+timestamp file
+# pragma wave option(output: null)
+
+# define BOOST_FT_PREPROCESSING_MODE
+
+# define BOOST_FT_HEADER \
+ BOOST_PP_SEQ_CAT((arity)(BOOST_FT_MAX_ARITY)(_)(BOOST_FT_mfp)).hpp
+ #define BOOST_FT_OUT_FILE \
+ BOOST_PP_STRINGIZE(../../../BOOST_FT_al_path/BOOST_FT_HEADER)
+
+# define BOOST_FT_al_path boost/function_types/detail/components_impl
+# include __FILE__
+# undef BOOST_FT_al_path
+
+# define BOOST_FT_al_path boost/function_types/detail/synthesize_impl
+# include __FILE__
+# undef BOOST_FT_al_path
+
+# define BOOST_FT_al_path boost/function_types/detail/classifier_impl
+# include __FILE__
+# undef BOOST_FT_al_path
+
+#elif !defined(BOOST_FT_mfp)
+
+# define BOOST_FT_mfp 0
+# include __FILE__
+# undef BOOST_FT_mfp
+
+# define BOOST_FT_mfp 1
+# include __FILE__
+# undef BOOST_FT_mfp
+
+#elif !defined(BOOST_FT_MAX_ARITY)
+
+# define BOOST_FT_FROM_ARITY 0
+# define BOOST_FT_MAX_ARITY 10
+# include __FILE__
+
+# define BOOST_FT_FROM_ARITY 10
+# define BOOST_FT_MAX_ARITY 20
+# include __FILE__
+
+# define BOOST_FT_FROM_ARITY 20
+# define BOOST_FT_MAX_ARITY 30
+# include __FILE__
+
+# define BOOST_FT_FROM_ARITY 30
+# define BOOST_FT_MAX_ARITY 40
+# include __FILE__
+
+# define BOOST_FT_FROM_ARITY 40
+# define BOOST_FT_MAX_ARITY 50
+# include __FILE__
+
+#else
+
+# pragma message(generating BOOST_FT_OUT_FILE)
+# pragma wave option(preserve: 2, output: BOOST_FT_OUT_FILE)
+# include <boost/function_types/detail/pp_arity_loop.hpp>
+# undef BOOST_FT_MAX_ARITY
+
+#endif
+
diff --git a/src/boost/libs/function_types/build/preprocess_cc_names.cpp b/src/boost/libs/function_types/build/preprocess_cc_names.cpp
new file mode 100644
index 000000000..803667c55
--- /dev/null
+++ b/src/boost/libs/function_types/build/preprocess_cc_names.cpp
@@ -0,0 +1,27 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#ifndef __WAVE__
+# error "Boost.Wave preprocessor required"
+#endif
+
+#pragma wave option(line: 0, preserve: 2)
+timestamp file
+#pragma wave option(output: null)
+
+#define BOOST_FT_PREPROCESSING_MODE
+
+
+#define BOOST_FT_OUT_FILE \
+ "../../../boost/function_types/detail/pp_cc_loop/preprocessed.hpp"
+#pragma message(generating BOOST_FT_OUT_FILE)
+#pragma wave option(output: BOOST_FT_OUT_FILE, preserve: 2)
+#include <boost/function_types/detail/pp_cc_loop/master.hpp>
+#pragma wave option(output: null)
+#undef BOOST_FT_OUT_FILE
+
diff --git a/src/boost/libs/function_types/build/preprocess_encoding.cpp b/src/boost/libs/function_types/build/preprocess_encoding.cpp
new file mode 100644
index 000000000..886bec33b
--- /dev/null
+++ b/src/boost/libs/function_types/build/preprocess_encoding.cpp
@@ -0,0 +1,45 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#ifndef __WAVE__
+# error "Boost.Wave preprocessor required"
+#endif
+
+#pragma wave option(line: 0, preserve: 2)
+timestamp file
+#pragma wave option(output: null)
+
+#define BOOST_FT_PREPROCESSING_MODE
+
+
+#define BOOST_FT_OUT_FILE \
+ "../../../boost/function_types/detail/pp_tags/preprocessed.hpp"
+#pragma message(generating BOOST_FT_OUT_FILE)
+#pragma wave option(output: BOOST_FT_OUT_FILE, preserve: 2)
+#include <boost/function_types/detail/pp_tags/master.hpp>
+#pragma wave option(output: null)
+#undef BOOST_FT_OUT_FILE
+
+#define BOOST_FT_OUT_FILE \
+ "../../../boost/function_types/detail/pp_variate_loop/preprocessed.hpp"
+#pragma message(generating BOOST_FT_OUT_FILE)
+#pragma wave option(output: BOOST_FT_OUT_FILE, preserve: 2)
+#include <boost/function_types/detail/pp_variate_loop/master.hpp>
+#pragma wave option(output: null)
+#undef BOOST_FT_OUT_FILE
+
+#define BOOST_FT_OUT_FILE \
+ "../../../boost/function_types/detail/pp_retag_default_cc/preprocessed.hpp"
+#pragma message(generating BOOST_FT_OUT_FILE)
+#pragma wave option(output: BOOST_FT_OUT_FILE, preserve: 2)
+#include <boost/function_types/detail/pp_retag_default_cc/master.hpp>
+#pragma wave option(output: null)
+
+#undef BOOST_FT_OUT_FILE
+
+
diff --git a/src/boost/libs/function_types/build/timestamps/arity_loops b/src/boost/libs/function_types/build/timestamps/arity_loops
new file mode 100644
index 000000000..f91091c8d
--- /dev/null
+++ b/src/boost/libs/function_types/build/timestamps/arity_loops
@@ -0,0 +1 @@
+timestamp file
diff --git a/src/boost/libs/function_types/build/timestamps/cc_names b/src/boost/libs/function_types/build/timestamps/cc_names
new file mode 100644
index 000000000..f91091c8d
--- /dev/null
+++ b/src/boost/libs/function_types/build/timestamps/cc_names
@@ -0,0 +1 @@
+timestamp file
diff --git a/src/boost/libs/function_types/build/timestamps/encoding b/src/boost/libs/function_types/build/timestamps/encoding
new file mode 100644
index 000000000..f91091c8d
--- /dev/null
+++ b/src/boost/libs/function_types/build/timestamps/encoding
@@ -0,0 +1 @@
+timestamp file
diff --git a/src/boost/libs/function_types/example/Jamfile b/src/boost/libs/function_types/example/Jamfile
new file mode 100644
index 000000000..08ab43dfe
--- /dev/null
+++ b/src/boost/libs/function_types/example/Jamfile
@@ -0,0 +1,20 @@
+
+# (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).
+
+#-------------------------------------------------------------------------------
+
+exe interpreter_example : interpreter_example.cpp ;
+
+exe result_of_example : result_of_example.cpp ;
+
+exe interface_example : interface_example.cpp ;
+
+exe fast_mem_fn_example : fast_mem_fn_example.cpp
+ : <include>. ; # needed for Boost.PP file iteration with some compilers
+
+exe macro_type_args_example : macro_type_args_example.cpp ;
+
+
diff --git a/src/boost/libs/function_types/example/detail/param_type.hpp b/src/boost/libs/function_types/example/detail/param_type.hpp
new file mode 100644
index 000000000..7c0fd5f2d
--- /dev/null
+++ b/src/boost/libs/function_types/example/detail/param_type.hpp
@@ -0,0 +1,71 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+// Metafunction to compute optimal parameter type for argument forwarding.
+
+// This header is not an FT example in itself -- it's used by some of them to
+// optimize argument forwarding.
+//
+// For more details see 'fast_mem_fn.hpp' in this directory or the documentation
+// of the CallTraits utility [1].
+//
+//
+// References
+// ==========
+//
+// [1] http://www.boost.org/libs/utility/call_traits.htm
+
+#ifndef BOOST_UTILITY_PARAM_TYPE_HPP_INCLUDED
+#define BOOST_UTILITY_PARAM_TYPE_HPP_INCLUDED
+
+#include <boost/config.hpp>
+
+#include <boost/type_traits/add_const.hpp>
+#include <boost/type_traits/add_reference.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+
+#include <boost/mpl/aux_/lambda_support.hpp>
+// #include <boost/type_traits/detail/template_arity_spec.hpp>
+
+// namespace boost
+namespace example
+{
+ namespace mpl = boost::mpl;
+
+ // namespace utility
+ // {
+ namespace param_type_detail
+ {
+ template<typename T>
+ struct by_ref_cond
+ {
+ typedef by_ref_cond type;
+ BOOST_STATIC_CONSTANT(bool,value = sizeof(void*) < sizeof(T));
+ };
+
+ template<typename T>
+ struct add_ref_to_const
+ : boost::add_reference< typename boost::add_const<T>::type >
+ { };
+ }
+
+ template<typename T>
+ struct param_type
+ : mpl::eval_if< param_type_detail::by_ref_cond<T>
+ , param_type_detail::add_ref_to_const<T>, mpl::identity<T> >
+ {
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,param_type,(T))
+ };
+ // }
+ // BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1,utility::param_type)
+}
+
+#endif
+
diff --git a/src/boost/libs/function_types/example/fast_mem_fn.hpp b/src/boost/libs/function_types/example/fast_mem_fn.hpp
new file mode 100644
index 000000000..2587c180f
--- /dev/null
+++ b/src/boost/libs/function_types/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
+
diff --git a/src/boost/libs/function_types/example/fast_mem_fn_example.cpp b/src/boost/libs/function_types/example/fast_mem_fn_example.cpp
new file mode 100644
index 000000000..381ee146e
--- /dev/null
+++ b/src/boost/libs/function_types/example/fast_mem_fn_example.cpp
@@ -0,0 +1,122 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+// See fast_mem_fn.hpp in this directory for details.
+
+#include <vector>
+#include <cassert>
+#include <iostream>
+#include <algorithm>
+#include <functional>
+
+#include <boost/timer.hpp>
+#include <boost/mem_fn.hpp>
+
+#include "fast_mem_fn.hpp"
+
+// test class that holds a single integer with getter function
+class test
+{
+ int val_id;
+public:
+
+ explicit test(int id)
+ : val_id(id)
+ { }
+
+ int id() const
+ { return val_id; }
+
+};
+
+// STL style comparator that applies the CriterionExtractor function to both
+// operands and compares the results with Comparator
+template<typename CriterionExtractor, typename Comparator>
+class test_compare
+{
+ CriterionExtractor fnc_criterion;
+ Comparator fnc_compare;
+public:
+
+ explicit test_compare(CriterionExtractor criterion, Comparator compare)
+ : fnc_criterion(criterion)
+ , fnc_compare(compare)
+ { }
+
+ template<typename T>
+ inline bool operator()(T const & lhs, T const & rhs) const
+ {
+ return fnc_compare(fnc_criterion(lhs),fnc_criterion(rhs));
+ }
+};
+
+// helper function to construct an instance of the test_compare comparator.
+template<typename CriterionExtractor, typename Comparator>
+test_compare<CriterionExtractor,Comparator>
+make_test_compare(CriterionExtractor criterion, Comparator compare)
+{
+ return test_compare<CriterionExtractor,Comparator>(criterion,compare);
+}
+
+// the test case: sort N test objects by id
+//
+// the objects are in ascending order before the test run and in descending
+// order after it
+
+static const unsigned N = 2000000;
+
+typedef std::vector<test> test_vector;
+
+
+void setup_test(test_vector & v)
+{
+ v.clear();
+ v.reserve(N);
+ for (unsigned i = 0; i < N; ++i)
+ v.push_back(test(i));
+}
+
+template<typename F> void do_test(test_vector & v, F criterion)
+{
+ std::sort(v.begin(),v.end(),make_test_compare(criterion,std::greater<int>()));
+ assert(v.begin()->id() == N-1);
+}
+
+
+// compare performance with boost::mem_fn
+int main()
+{
+ test_vector v;
+ boost::timer t;
+ double time1, time2;
+
+ std::cout <<
+ "Test case: sorting " << N << " objects.\n\n"
+ "Criterion accessor called with | elasped seconds\n"
+ "-------------------------------|----------------" << std::endl;
+
+ setup_test(v);
+ t.restart();
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1400)
+ do_test(v, BOOST_EXAMPLE_FAST_MEM_FN(& test::id));
+#else // MSVC<8 does not like the implementation of the deduction macro:
+ do_test(v, ::example::fast_mem_fn< int (test::*)() const, & test::id >());
+#endif
+ time1 = t.elapsed();
+ std::cout << "fast_mem_fn | " << time1 << std::endl;
+
+ setup_test(v);
+ t.restart();
+ do_test(v, boost::mem_fn(& test::id));
+ time2 = t.elapsed();
+ std::cout << "mem_fn | " << time2 << std::endl;
+
+ std::cout << '\n' << (time2/time1-1)*100 << "% speedup" << std::endl;
+
+ return 0;
+}
+
diff --git a/src/boost/libs/function_types/example/interface.hpp b/src/boost/libs/function_types/example/interface.hpp
new file mode 100644
index 000000000..cadf740d2
--- /dev/null
+++ b/src/boost/libs/function_types/example/interface.hpp
@@ -0,0 +1,361 @@
+
+// (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 interfaces.
+//
+// Detailed description
+// ====================
+//
+// An interface is a collection of member function prototypes that may be
+// implemented by classes. Objects of classes that implement the interface can
+// then be assigned to an interface variable through which the interface's
+// functions can be called.
+//
+// Interfaces are a feature of the Java programming language [Gosling] and the
+// most obvious way to model interfaces in C++ is (multiple) inheritance.
+// Using inheritance for this purpose, however, is neither the most efficient
+// nor the most flexible solution, because:
+//
+// - all functions must be virtual,
+//
+// => a function that calls another function of the interface must do so
+// via virtual dispatch (as opposed to inlining)
+// => a class can not implement an interface's (overloaded) function via
+// a function template
+//
+// - inhertitance is intrusive
+//
+// => object size increases
+// => client's are always polymorphic
+// => dependencies cause tighter coupling
+//
+// Fortunately it is possible to eliminate all the drawbacks mentioned above
+// based on an alternative implementation proposed by David Abrahams.
+// We'll add some detail to the original scheme (see [Abrahams]) such as
+// support for overloaded and const qualified functions.
+// The implementation in this example uses Boost.FunctionTypes to shift
+// metaprogramming code from the preprocessor into templates, to reduce
+// preprocessing time and increase maintainability.
+//
+//
+// Limitations
+// ===========
+//
+// There is no lifetime management as implemented by the Boost candidate
+// Interfaces library (see [Turkanis]).
+//
+// This example does not compile with Visual C++. Template argument deduction
+// from the result of the address-of operator does not work properly with this
+// compiler. It is possible to partially work around the problem, but it isn't
+// done here for the sake of readability.
+//
+//
+// Bibliography
+// ============
+//
+// [Gosling] Gosling, J., Joy, B., Steele, G. The Java Language Specification
+// http://java.sun.com/docs/books/jls/third_edition/html/interfaces.html
+//
+// [Abrahams] Abrahams, D. Proposal: interfaces, Post to newsgroup comp.std.c++
+// http://groups.google.com/group/comp.std.c++/msg/85af30a61bf677e4
+//
+// [Turkanis] Turkanis, J., Diggins, C. Boost candidate Interfaces library
+// http://www.kangaroologic.com/interfaces/libs/interfaces/doc/index.html
+
+#include <cstddef>
+
+#include <boost/function_types/function_pointer.hpp>
+#include <boost/function_types/member_function_pointer.hpp>
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#include <boost/utility/addressof.hpp>
+
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/joint_view.hpp>
+#include <boost/mpl/single_view.hpp>
+#include <boost/mpl/transform_view.hpp>
+
+#include <boost/preprocessor/seq/seq.hpp>
+#include <boost/preprocessor/seq/enum.hpp>
+#include <boost/preprocessor/seq/elem.hpp>
+#include <boost/preprocessor/seq/size.hpp>
+#include <boost/preprocessor/tuple/elem.hpp>
+#include <boost/preprocessor/arithmetic/dec.hpp>
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/facilities/empty.hpp>
+#include <boost/preprocessor/facilities/identity.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/iteration/local.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+
+#include "detail/param_type.hpp"
+
+namespace example
+{
+ namespace ft = boost::function_types;
+ namespace mpl = boost::mpl;
+ using namespace mpl::placeholders;
+
+ // join a single type and an MPL-sequence
+ // in some ways similar to mpl::push_front (but mpl::push_front requires
+ // an MPL Extensible Sequence and this template does not)
+ template<typename T, typename Seq>
+ struct concat_view
+ : mpl::joint_view<mpl::single_view<T>, Seq>
+ { };
+
+ // metafunction returning a function pointer type for a vtable entry
+ template<typename Inf>
+ struct vtable_entry
+ : ft::function_pointer
+ < concat_view< typename Inf::result, mpl::transform_view<
+ typename Inf::params, param_type<_> > > >
+ { };
+
+ // the expression '& member<MetaInfo,Tag>::wrap<& Class::Function> ' in an
+ // assignment context binds the member function Function of Class with the
+ // properties described by MetaInfo and Tag to the corresponding vtable
+ // entry
+ template<typename Inf, typename Tag>
+ struct member
+ {
+ typedef typename ft::member_function_pointer
+ < concat_view<typename Inf::result,typename Inf::params>,Tag
+ >::type
+ mem_func_ptr;
+
+ typedef typename mpl::at_c<typename Inf::params,0>::type context;
+
+ template<mem_func_ptr MemFuncPtr>
+ static typename Inf::result wrap(void* c)
+ {
+ return (reinterpret_cast<context*>(c)->*MemFuncPtr)();
+ }
+ template<mem_func_ptr MemFuncPtr, typename T0>
+ static typename Inf::result wrap(void* c, T0 a0)
+ {
+ return (reinterpret_cast<context*>(c)->*MemFuncPtr)(a0);
+ }
+ template<mem_func_ptr MemFuncPtr, typename T0, typename T1>
+ static typename Inf::result wrap(void* c, T0 a0, T1 a1)
+ {
+ return (reinterpret_cast<context*>(c)->*MemFuncPtr)(a0,a1);
+ }
+ // continue with the preprocessor (the scheme should be clear, by now)
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<mem_func_ptr MemFuncPtr, BOOST_PP_ENUM_PARAMS(n,typename T)> \
+ static typename Inf::result wrap(void* c, \
+ BOOST_PP_ENUM_BINARY_PARAMS(n,T,a)) \
+ { \
+ return (reinterpret_cast<context*>(c)->*MemFuncPtr)( \
+ BOOST_PP_ENUM_PARAMS(n,a) ); \
+ }
+ #define BOOST_PP_LOCAL_LIMITS (3,BOOST_FT_MAX_ARITY-1)
+ #include BOOST_PP_LOCAL_ITERATE()
+ };
+
+ // extract a parameter by index
+ template<typename Inf, std::size_t Index>
+ struct param
+ : param_type< typename mpl::at_c< typename Inf::params,Index>::type >
+ { };
+}
+
+// the interface definition on the client's side
+#define BOOST_EXAMPLE_INTERFACE(name,def) \
+ class name \
+ { \
+ struct vtable \
+ { \
+ BOOST_EXAMPLE_INTERFACE__MEMBERS(def,VTABLE) \
+ }; \
+ \
+ vtable const * ptr_vtable; \
+ void * ptr_that; \
+ \
+ template<class T> struct vtable_holder \
+ { \
+ static vtable const val_vtable; \
+ }; \
+ \
+ public: \
+ \
+ template<class T> \
+ inline name (T & that) \
+ : ptr_vtable(& vtable_holder<T>::val_vtable) \
+ , ptr_that(boost::addressof(that)) \
+ { } \
+ \
+ BOOST_EXAMPLE_INTERFACE__MEMBERS(def,FUNCTION) \
+ }; \
+ \
+ template<typename T> \
+ name ::vtable const name ::vtable_holder<T>::val_vtable \
+ = { BOOST_EXAMPLE_INTERFACE__MEMBERS(def,INIT_VTABLE) }
+
+
+#ifdef BOOST_PP_NIL // never defined -- a comment with syntax highlighting
+
+BOOST_EXAMPLE_INTERFACE( interface_x,
+ (( a_func, (void)(int), const_qualified ))
+ (( another_func, (int), non_const ))
+);
+
+// expands to:
+class interface_x
+{
+ struct vtable
+ {
+ // meta information for first function
+ template<typename T = void*> struct inf0
+ {
+ typedef void result;
+ typedef ::boost::mpl::vector< T, int > params;
+ };
+ // function pointer with void* context pointer and parameters optimized
+ // for forwarding
+ ::example::vtable_entry<inf0<> >::type func0;
+
+ // second function
+ template<typename T = void*> struct inf1
+ {
+ typedef int result;
+ typedef ::boost::mpl::vector< T > params;
+ };
+ ::example::vtable_entry<inf1<> >::type func1;
+ };
+
+ // data members
+ vtable const * ptr_vtable;
+ void * ptr_that;
+
+ // this template is instantiated for every class T this interface is created
+ // from, causing the compiler to emit an initialized vtable for this type
+ // (see aggregate assignment, below)
+ template<class T> struct vtable_holder
+ {
+ static vtable const val_vtable;
+ };
+
+public:
+
+ // converting ctor, creates an interface from an arbitrary class
+ template<class T>
+ inline interface_x (T & that)
+ : ptr_vtable(& vtable_holder<T>::val_vtable)
+ , ptr_that(boost::addressof(that))
+ { }
+
+ // the member functions from the interface definition, parameters are
+ // optimized for forwarding
+
+ inline vtable::inf0<> ::result a_func (
+ ::example::param<vtable::inf0<>,1>::type p0) const
+ {
+ return ptr_vtable-> func0(ptr_that , p0);
+ }
+
+ inline vtable::inf1<> ::result another_func ()
+ {
+ return ptr_vtable-> func1(ptr_that );
+ }
+};
+
+template<typename T>
+interface_x ::vtable const interface_x ::vtable_holder<T>::val_vtable =
+{
+ // instantiate function templates that wrap member function pointers (which
+ // are known at compile time) by taking their addresses in assignment to
+ // function pointer context
+ & ::example::member< vtable::inf0<T>, ::example::ft:: const_qualified >
+ ::template wrap < &T:: a_func >
+, & ::example::member< vtable::inf1<T>, ::example::ft:: non_const >
+ ::template wrap < &T:: another_func >
+};
+#endif
+
+// preprocessing code details
+
+// iterate all of the interface's members and invoke a macro (prefixed with
+// BOOST_EXAMPLE_INTERFACE_)
+#define BOOST_EXAMPLE_INTERFACE__MEMBERS(seq,macro) \
+ BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(seq), \
+ BOOST_EXAMPLE_INTERFACE__ ## macro,seq)
+
+// extract signature sequence from entry
+#define BOOST_EXAMPLE_INTERFACE__VTABLE(z,i,seq) \
+ BOOST_EXAMPLE_INTERFACE__VTABLE_I(z,i, \
+ BOOST_PP_TUPLE_ELEM(3,1,BOOST_PP_SEQ_ELEM(i,seq)))
+
+// split the signature sequence result/params and insert T at the beginning of
+// the params part
+#define BOOST_EXAMPLE_INTERFACE__VTABLE_I(z,i,seq) \
+ BOOST_EXAMPLE_INTERFACE__VTABLE_II(z,i, \
+ BOOST_PP_SEQ_HEAD(seq),(T)BOOST_PP_SEQ_TAIL(seq))
+
+// emit the meta information structure and function pointer declaration
+#define BOOST_EXAMPLE_INTERFACE__VTABLE_II(z,i,result_type,param_types) \
+ template<typename T = void*> \
+ struct BOOST_PP_CAT(inf,i) \
+ { \
+ typedef result_type result; \
+ typedef ::boost::mpl::vector< BOOST_PP_SEQ_ENUM(param_types) > params; \
+ }; \
+ ::example::vtable_entry<BOOST_PP_CAT(inf,i)<> >::type BOOST_PP_CAT(func,i);
+
+// extract tuple entry from sequence and precalculate the name of the function
+// pointer variable
+#define BOOST_EXAMPLE_INTERFACE__INIT_VTABLE(z,i,seq) \
+ BOOST_EXAMPLE_INTERFACE__INIT_VTABLE_I(i,seq,BOOST_PP_CAT(func,i), \
+ BOOST_PP_SEQ_ELEM(i,seq))
+
+// emit a function pointer expression that encapsulates the corresponding
+// member function of T
+#define BOOST_EXAMPLE_INTERFACE__INIT_VTABLE_I(i,seq,func,desc) \
+ BOOST_PP_COMMA_IF(i) & ::example::member< BOOST_PP_CAT(vtable::inf,i)<T>, \
+ ::example::ft:: BOOST_PP_TUPLE_ELEM(3,2,desc) >::template wrap \
+ < &T:: BOOST_PP_TUPLE_ELEM(3,0,desc) >
+
+// extract tuple entry from sequence
+#define BOOST_EXAMPLE_INTERFACE__FUNCTION(z,i,seq) \
+ BOOST_EXAMPLE_INTERFACE__FUNCTION_I(z,i,BOOST_PP_SEQ_ELEM(i,seq))
+
+// precalculate function name, arity, name of meta info structure and cv-
+// qualifiers
+#define BOOST_EXAMPLE_INTERFACE__FUNCTION_I(z,i,desc) \
+ BOOST_EXAMPLE_INTERFACE__FUNCTION_II(z,i, \
+ BOOST_PP_TUPLE_ELEM(3,0,desc), \
+ BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(3,1,desc))), \
+ BOOST_PP_CAT(vtable::inf,i)<>, \
+ BOOST_PP_CAT(BOOST_EXAMPLE_INTERFACE___,BOOST_PP_TUPLE_ELEM(3,2,desc)) \
+ )
+
+// emit the definition for a member function of the interface
+#define BOOST_EXAMPLE_INTERFACE__FUNCTION_II(z,i,name,arity,types,cv) \
+ inline types ::result name \
+ (BOOST_PP_ENUM_ ## z (arity,BOOST_EXAMPLE_INTERFACE__PARAM,types)) cv() \
+ { \
+ return ptr_vtable-> BOOST_PP_CAT(func,i)(ptr_that \
+ BOOST_PP_ENUM_TRAILING_PARAMS_Z(z,arity,p)); \
+ }
+
+// emit a parameter of the function definition
+#define BOOST_EXAMPLE_INTERFACE__PARAM(z,j,types) \
+ ::example::param<types,BOOST_PP_INC(j)>::type BOOST_PP_CAT(p,j)
+
+// helper macros to map 'const_qualified' to 'const' an 'non_const' to ''
+#define BOOST_EXAMPLE_INTERFACE___const_qualified BOOST_PP_IDENTITY(const)
+#define BOOST_EXAMPLE_INTERFACE___non_const BOOST_PP_EMPTY
+
+
diff --git a/src/boost/libs/function_types/example/interface_example.cpp b/src/boost/libs/function_types/example/interface_example.cpp
new file mode 100644
index 000000000..6b7f8d946
--- /dev/null
+++ b/src/boost/libs/function_types/example/interface_example.cpp
@@ -0,0 +1,80 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+// See interface.hpp in this directory for details.
+
+#include <iostream>
+#include <typeinfo>
+
+#include "interface.hpp"
+
+
+BOOST_EXAMPLE_INTERFACE( interface_x,
+ (( a_func, (void)(int) , const_qualified ))
+ (( a_func, (void)(long), const_qualified ))
+ (( another_func, (int) , non_const ))
+);
+
+
+// two classes that implement interface_x
+
+struct a_class
+{
+ void a_func(int v) const
+ {
+ std::cout << "a_class::void a_func(int v = " << v << ")" << std::endl;
+ }
+
+ void a_func(long v) const
+ {
+ std::cout << "a_class::void a_func(long v = " << v << ")" << std::endl;
+ }
+
+ int another_func()
+ {
+ std::cout << "a_class::another_func() = 3" << std::endl;
+ return 3;
+ }
+};
+
+struct another_class
+{
+ // note: overloaded a_func implemented as a function template
+ template<typename T>
+ void a_func(T v) const
+ {
+ std::cout <<
+ "another_class::void a_func(T v = " << v << ")"
+ " [ T = " << typeid(T).name() << " ]" << std::endl;
+ }
+
+ int another_func()
+ {
+ std::cout << "another_class::another_func() = 5" << std::endl;
+ return 5;
+ }
+};
+
+
+// both classes above can be assigned to the interface variable and their
+// member functions can be called through it
+int main()
+{
+ a_class x;
+ another_class y;
+
+ interface_x i(x);
+ i.a_func(12);
+ i.a_func(77L);
+ i.another_func();
+
+ i = y;
+ i.a_func(13);
+ i.a_func(21L);
+ i.another_func();
+}
+
diff --git a/src/boost/libs/function_types/example/interpreter.hpp b/src/boost/libs/function_types/example/interpreter.hpp
new file mode 100644
index 000000000..72cd78b0e
--- /dev/null
+++ b/src/boost/libs/function_types/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);
+ }
+ }
+
+}
+
diff --git a/src/boost/libs/function_types/example/interpreter_example.cpp b/src/boost/libs/function_types/example/interpreter_example.cpp
new file mode 100644
index 000000000..9e6118b6e
--- /dev/null
+++ b/src/boost/libs/function_types/example/interpreter_example.cpp
@@ -0,0 +1,56 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <string>
+#include <iostream>
+#include <stdexcept>
+
+#include "interpreter.hpp"
+
+void echo(std::string const & s)
+{
+ std::cout << s << std::endl;
+}
+
+void add(int a, int b)
+{
+ std::cout << a + b << std::endl;
+}
+
+void repeat(std::string const & s, int n)
+{
+ while (--n >= 0) std::cout << s;
+ std::cout << std::endl;
+}
+
+int main()
+{
+ example::interpreter interpreter;
+
+ interpreter.register_function("echo", & echo);
+ interpreter.register_function("add", & add);
+ interpreter.register_function("repeat", & repeat);
+
+ std::string line = "nonempty";
+ while (! line.empty())
+ {
+ std::cout << std::endl << "] ", std::getline(std::cin,line);
+
+ try
+ {
+ interpreter.parse_input(line);
+ }
+ catch (std::runtime_error &error)
+ {
+ std::cerr << error.what() << std::endl;
+ }
+ }
+
+ return 0;
+}
+
diff --git a/src/boost/libs/function_types/example/macro_type_args.hpp b/src/boost/libs/function_types/example/macro_type_args.hpp
new file mode 100644
index 000000000..350052456
--- /dev/null
+++ b/src/boost/libs/function_types/example/macro_type_args.hpp
@@ -0,0 +1,73 @@
+
+// (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 utility to accept a type expression, that may
+// contain commas to a macro.
+//
+//
+// Detailed description
+// ====================
+//
+// Accepting a type as macro argument can cause problems if the type expression
+// contains commas:
+//
+// #define MY_MACRO(a_type)
+// ...
+// MY_MACRO(std::map<int,int>) // ERROR (wrong number of macro arguments)
+//
+// This problem can be solved by pasing using a parenthesized type
+//
+// MY_MACRO((std::map<int,int>) // OK
+//
+// but then there is no way to remove the parentheses in the macro argument
+// with the preprocessor.
+// We can, however, form a pointer to a function with a single argument (the
+// parentheses become part of the type) and extract the argument with template
+// metaprogramming:
+//
+// // Inside the macro definition
+//
+// typename mpl::front< parameter_types<void(*)a_type> >::type
+//
+// This code snippet does not read too expressive so we use another macro
+// to encapsulate the solution:
+//
+// // Inside the macro definition
+//
+// BOOST_EXAMPLE_MACRO_TYPE_ARGUMENT(a_type)
+//
+// As a generalization of this technique we can accept a comma-separated list of
+// types. Omitting the mpl::front invocation gives us an MPL-sequence.
+//
+//
+// Limitations
+// ===========
+//
+// - only works for types that are valid function arguments
+//
+// Acknowledgments
+// ===============
+//
+// Thanks go to Dave Abrahams for letting me know this technique.
+
+#ifndef BOOST_EXAMPLE_MACRO_TYPE_ARGUMENT_HPP_INCLUDED
+#define BOOST_EXAMPLE_MACRO_TYPE_ARGUMENT_HPP_INCLUDED
+
+#include <boost/function_types/parameter_types.hpp>
+#include <boost/mpl/front.hpp>
+
+#define BOOST_EXAMPLE_MACRO_TYPE_ARGUMENT(parenthesized_type) \
+ boost::mpl::front< \
+ BOOST_EXAMPLE_MACRO_TYPE_LIST_ARGUMENT(parenthesized_type) >::type
+
+#define BOOST_EXAMPLE_MACRO_TYPE_LIST_ARGUMENT(parenthesized_types) \
+ ::boost::function_types::parameter_types< void(*) parenthesized_types >
+
+
+#endif
+
diff --git a/src/boost/libs/function_types/example/macro_type_args_example.cpp b/src/boost/libs/function_types/example/macro_type_args_example.cpp
new file mode 100644
index 000000000..9f8388381
--- /dev/null
+++ b/src/boost/libs/function_types/example/macro_type_args_example.cpp
@@ -0,0 +1,71 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+// See macro_type_arugment.hpp in this directory for details.
+
+#include <string>
+#include <typeinfo>
+#include <iostream>
+
+#include <boost/mpl/begin_end.hpp>
+#include <boost/mpl/deref.hpp>
+
+#include "macro_type_args.hpp"
+
+
+#define TYPE_NAME(parenthesized_type) \
+ typeid(BOOST_EXAMPLE_MACRO_TYPE_ARGUMENT(parenthesized_type)).name()
+
+namespace example
+{
+ namespace mpl = boost::mpl;
+
+ template<class Curr, class End>
+ struct mpl_seq_to_string_impl
+ {
+ static std::string get(std::string const & prev)
+ {
+ typedef typename mpl::next<Curr>::type next_pos;
+ typedef typename mpl::deref<Curr>::type type;
+
+ return mpl_seq_to_string_impl<next_pos,End>::get(
+ prev + (prev.empty()? '\0' : ',') + typeid(type).name() );
+ }
+ };
+ template<class End>
+ struct mpl_seq_to_string_impl<End, End>
+ {
+ static std::string get(std::string const & prev)
+ {
+ return prev;
+ }
+ };
+
+ template<class Seq>
+ std::string mpl_seq_to_string()
+ {
+ typedef typename mpl::begin<Seq>::type begin;
+ typedef typename mpl::end<Seq>::type end;
+
+ return mpl_seq_to_string_impl<begin, end>::get("");
+ }
+
+}
+
+#define TYPE_NAMES(parenthesized_types) \
+ ::example::mpl_seq_to_string< \
+ BOOST_EXAMPLE_MACRO_TYPE_LIST_ARGUMENT(parenthesized_types) >()
+
+int main()
+{
+ std::cout << TYPE_NAME((int)) << std::endl;
+
+ std::cout << TYPE_NAMES((int,char)) << std::endl;
+ std::cout << TYPE_NAMES((int,char,long)) << std::endl;
+
+}
+
diff --git a/src/boost/libs/function_types/example/result_of.hpp b/src/boost/libs/function_types/example/result_of.hpp
new file mode 100644
index 000000000..7c3341af4
--- /dev/null
+++ b/src/boost/libs/function_types/example/result_of.hpp
@@ -0,0 +1,86 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+//
+// Reimplementation of the Boost result_of utility (see [Gregor01] and
+// [Gregor02]).
+//
+//
+// Detailed description
+// ====================
+//
+// This example implements the functionality of the Boost result_of utility.
+// Because of FunctionTypes we get away without repetitive code and the Boost
+// Preprocessor library.
+//
+//
+// Bibliography
+// ============
+//
+// [Gregor01] Gregor, D. The Boost result_of utility
+// http://www.boost.org/libs/utility
+//
+// [Gregor02] Gregor, D. A uniform method for computing function object return
+// types (revision 1)
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1454.html
+
+#include <boost/function_types/result_type.hpp>
+#include <boost/function_types/is_callable_builtin.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/has_xxx.hpp>
+
+namespace example
+{
+ namespace ft = boost::function_types;
+ namespace mpl = boost::mpl;
+
+ template<typename F> struct result_of;
+
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
+
+ template<typename F>
+ struct result_type_member
+ {
+ typedef typename F::result_type type;
+ };
+
+ template<typename F, typename Desc>
+ struct result_member_template
+ {
+ typedef typename F::template result<Desc>::type type;
+ };
+
+#if !BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x564))
+ template<typename F>
+ struct result_member_template< F, F(void) >
+ {
+ typedef void type;
+ };
+#endif
+
+ template<typename F, typename Desc>
+ struct result_of_impl
+ : mpl::eval_if
+ < ft::is_callable_builtin<F>
+ , ft::result_type<F>
+ , mpl::eval_if
+ < has_result_type<F>
+ , result_type_member<F>
+ , result_member_template<F,Desc>
+ > >
+ { };
+ }
+
+ template<typename Desc>
+ struct result_of
+ : detail::result_of_impl< typename ft::result_type<Desc>::type, Desc >
+ { };
+}
+
diff --git a/src/boost/libs/function_types/example/result_of_example.cpp b/src/boost/libs/function_types/example/result_of_example.cpp
new file mode 100644
index 000000000..a8fe2d239
--- /dev/null
+++ b/src/boost/libs/function_types/example/result_of_example.cpp
@@ -0,0 +1,59 @@
+
+// (C) Copyright Douglas Gregor 2003-2004.
+// (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 file is a modified copy of the original Boost.ResultOf test-suite.
+// See result_of.hpp in this directory for details.
+
+
+#include "result_of.hpp"
+
+#include <utility>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+struct int_result_type { typedef int result_type; };
+
+struct int_result_of
+{
+ template<typename F> struct result { typedef int type; };
+};
+
+struct int_result_type_and_float_result_of
+{
+ typedef int result_type;
+ template<typename F> struct result { typedef float type; };
+};
+
+struct X {};
+
+int main()
+{
+ using namespace boost;
+ namespace e = example;
+
+ typedef int (*func_ptr)(float, double);
+ typedef int (&func_ref)(float, double);
+ typedef int (X::*mem_func_ptr)(float);
+ typedef int (X::*mem_func_ptr_c)(float) const;
+ typedef int (X::*mem_func_ptr_v)(float) volatile;
+ typedef int (X::*mem_func_ptr_cv)(float) const volatile;
+
+ BOOST_STATIC_ASSERT((is_same<e::result_of<int_result_type(float)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same<e::result_of<int_result_of(double)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same<e::result_of<int_result_of(void)>::type, void>::value));
+ BOOST_STATIC_ASSERT((is_same<e::result_of<const int_result_of(double)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same<e::result_of<volatile int_result_of(void)>::type, void>::value));
+ BOOST_STATIC_ASSERT((is_same<e::result_of<int_result_type_and_float_result_of(char)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same<e::result_of<func_ptr(char, float)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same<e::result_of<func_ref(char, float)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same<e::result_of<mem_func_ptr(X,char)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same<e::result_of<mem_func_ptr_c(X,char)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same<e::result_of<mem_func_ptr_v(X,char)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same<e::result_of<mem_func_ptr_cv(X,char)>::type, int>::value));
+ return 0;
+}
diff --git a/src/boost/libs/function_types/index.html b/src/boost/libs/function_types/index.html
new file mode 100644
index 000000000..ee4ce6e07
--- /dev/null
+++ b/src/boost/libs/function_types/index.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <meta http-equiv="refresh" content="0; URL=doc/html/index.html">
+ </head>
+ <body>
+ <p>Automatic redirection failed, please go to
+ <a href="doc/html/index.html">doc/html/index.html</a>.</p>
+ <p>Copyright&nbsp;Tobias Schwinger 2005-2007</p>
+ <p>Distributed under the Boost Software License, Version 1.0. (See accompanying file <a href="../../LICENSE_1_0.txt">
+ LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>).</p>
+ </body>
+</html>
+
diff --git a/src/boost/libs/function_types/meta/libraries.json b/src/boost/libs/function_types/meta/libraries.json
new file mode 100644
index 000000000..44b499eae
--- /dev/null
+++ b/src/boost/libs/function_types/meta/libraries.json
@@ -0,0 +1,15 @@
+{
+ "key": "function_types",
+ "name": "Function Types",
+ "authors": [
+ "Tobias Schwinger"
+ ],
+ "description": "Boost.FunctionTypes provides functionality to classify, decompose and synthesize function, function pointer, function reference and pointer to member types.",
+ "category": [
+ "Generic",
+ "Metaprogramming"
+ ],
+ "maintainers": [
+ "Tobias Schwinger <tschwinger -at- isonews2.com>"
+ ]
+}
diff --git a/src/boost/libs/function_types/test/Jamfile b/src/boost/libs/function_types/test/Jamfile
new file mode 100644
index 000000000..e652c466b
--- /dev/null
+++ b/src/boost/libs/function_types/test/Jamfile
@@ -0,0 +1,89 @@
+
+# (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).
+
+#-------------------------------------------------------------------------------
+
+import testing ;
+
+{
+ test-suite function_types :
+
+ # Classification
+
+ [ compile classification/is_function.cpp ]
+ [ compile classification/is_function_pointer.cpp ]
+ [ compile classification/is_function_reference.cpp ]
+ [ compile classification/is_member_function_pointer.cpp ]
+ [ compile classification/is_member_object_pointer.cpp ]
+ [ compile classification/is_callable_builtin.cpp ]
+ [ compile classification/is_nonmember_callable_builtin.cpp ]
+ [ compile classification/is_member_pointer.cpp ]
+
+ [ compile classification/is_cv_mem_func_ptr.cpp ]
+ [ compile classification/is_variadic.cpp ]
+ [ compile classification/is_cv_pointer.cpp ]
+ # [ compile classification/is_cv_function.cpp ]
+
+ # Decomposition
+
+ [ compile decomposition/components.cpp ]
+ [ compile decomposition/result_type.cpp ]
+ [ compile decomposition/function_arity.cpp ]
+ [ compile decomposition/parameter_types.cpp ]
+
+ [ compile decomposition/components_seq.cpp ]
+ [ compile decomposition/class_type_transform.cpp ]
+
+ [ compile-fail decomposition/result_type_fail.cpp ]
+ [ compile-fail decomposition/parameter_types_fail.cpp ]
+ [ compile-fail decomposition/function_arity_fail.cpp ]
+
+ # Synthesis
+
+ [ compile synthesis/function_type.cpp ]
+ [ compile synthesis/function_pointer.cpp ]
+ [ compile synthesis/function_reference.cpp ]
+ [ compile synthesis/member_function_pointer.cpp ]
+ [ compile synthesis/member_object_pointer.cpp ]
+
+ [ compile synthesis/transformation.cpp ]
+ [ compile synthesis/mem_func_ptr_cv1.cpp ]
+ [ compile synthesis/mem_func_ptr_cv2.cpp ]
+ [ compile synthesis/mem_func_ptr_cv_ptr_to_this.cpp ]
+ [ compile synthesis/variadic_function_synthesis.cpp ]
+ # [ compile synthesis/cv_function_synthesis.cpp ]
+
+ # Reconfiguration
+
+ [ compile reconfiguration/preprocessing_mode.cpp ]
+ [ compile reconfiguration/partial_arity_preprocessing.cpp ]
+ [ compile reconfiguration/cc_preprocessing.cpp ]
+
+ # Custom calling conventions
+
+ [ compile custom_ccs/nonmember_ccs.cpp : <address-model>64:<build>no ]
+ [ compile custom_ccs/nonmember_ccs_exact.cpp : <address-model>64:<build>no ]
+ [ compile custom_ccs/member_ccs.cpp : <address-model>64:<build>no ]
+ [ compile custom_ccs/member_ccs_exact.cpp : <address-model>64:<build>no ]
+
+ # Property tag
+
+ [ compile custom_ccs/property_tag.cpp ]
+
+ # Code from the examples
+
+ [ compile ../example/interpreter_example.cpp ]
+ [ compile ../example/result_of_example.cpp ]
+ [ compile ../example/interface_example.cpp ]
+ [ compile ../example/fast_mem_fn_example.cpp
+ # needed for Boost.PP file iteration with some compilers
+ : <include>../example
+ ]
+ [ compile ../example/macro_type_args_example.cpp ]
+ ;
+}
+
+
diff --git a/src/boost/libs/function_types/test/classification/is_callable_builtin.cpp b/src/boost/libs/function_types/test/classification/is_callable_builtin.cpp
new file mode 100644
index 000000000..d65f6f363
--- /dev/null
+++ b/src/boost/libs/function_types/test/classification/is_callable_builtin.cpp
@@ -0,0 +1,86 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/function_types/is_callable_builtin.hpp>
+
+namespace ft = boost::function_types;
+
+typedef void func();
+typedef void (*func_ptr)();
+typedef void (&func_ref)();
+class C;
+typedef void (C::*mem_func_ptr)();
+typedef void (C::*c_mem_func_ptr)() const;
+typedef void (C::*v_mem_func_ptr)() volatile;
+typedef void (C::*cv_mem_func_ptr)() const volatile;
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< func >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< func_ref >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< c_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< v_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< cv_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< mem_func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< C >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< int >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< int* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< int** >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< int& >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< int[] >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< int[1] >
+));
+
diff --git a/src/boost/libs/function_types/test/classification/is_cv_function.cpp b/src/boost/libs/function_types/test/classification/is_cv_function.cpp
new file mode 100644
index 000000000..176300c90
--- /dev/null
+++ b/src/boost/libs/function_types/test/classification/is_cv_function.cpp
@@ -0,0 +1,142 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/function_types/is_function.hpp>
+
+namespace ft = boost::function_types;
+
+template<typename C, typename T>
+void test_non_cv(T C::*)
+{
+ BOOST_MPL_ASSERT((
+ ft::is_function<T, ft::non_const >
+ ));
+
+ BOOST_MPL_ASSERT((
+ ft::is_function<T, ft::non_volatile >
+ ));
+
+ BOOST_MPL_ASSERT((
+ ft::is_function<T, ft::tag<ft::non_const,ft::non_volatile> >
+ ));
+
+ BOOST_MPL_ASSERT_NOT((
+ ft::is_function<T, ft::const_qualified >
+ ));
+
+ BOOST_MPL_ASSERT_NOT((
+ ft::is_function<T, ft::volatile_qualified >
+ ));
+
+ BOOST_MPL_ASSERT_NOT((
+ ft::is_function<T, ft::tag<ft::const_qualified,ft::volatile_qualified> >
+ ));
+}
+
+template<typename C, typename T>
+void test_c_non_v(T C::*)
+{
+ BOOST_MPL_ASSERT((
+ ft::is_function<T, ft::const_qualified >
+ ));
+
+ BOOST_MPL_ASSERT((
+ ft::is_function<T, ft::non_volatile >
+ ));
+
+ BOOST_MPL_ASSERT((
+ ft::is_function<T, ft::tag<ft::const_qualified,ft::non_volatile> >
+ ));
+
+ BOOST_MPL_ASSERT_NOT((
+ ft::is_function<T, ft::non_const >
+ ));
+
+ BOOST_MPL_ASSERT_NOT((
+ ft::is_function<T, ft::volatile_qualified >
+ ));
+
+ BOOST_MPL_ASSERT_NOT((
+ ft::is_function<T, ft::tag<ft::non_const,ft::volatile_qualified> >
+ ));
+}
+
+template<typename C, typename T>
+void test_v_non_c(T C::*)
+{
+ BOOST_MPL_ASSERT((
+ ft::is_function<T, ft::non_const >
+ ));
+
+ BOOST_MPL_ASSERT((
+ ft::is_function<T, ft::volatile_qualified >
+ ));
+
+ BOOST_MPL_ASSERT((
+ ft::is_function<T, ft::tag<ft::non_const,ft::volatile_qualified> >
+ ));
+
+ BOOST_MPL_ASSERT_NOT((
+ ft::is_function<T, ft::const_qualified >
+ ));
+
+ BOOST_MPL_ASSERT_NOT((
+ ft::is_function<T, ft::non_volatile >
+ ));
+
+ BOOST_MPL_ASSERT_NOT((
+ ft::is_function<T, ft::tag<ft::const_qualified,ft::non_volatile> >
+ ));
+}
+
+template<typename C, typename T>
+void test_cv(T C::*)
+{
+ BOOST_MPL_ASSERT((
+ ft::is_function<T, ft::const_qualified >
+ ));
+
+ BOOST_MPL_ASSERT((
+ ft::is_function<T, ft::volatile_qualified >
+ ));
+
+ BOOST_MPL_ASSERT((
+ ft::is_function<T, ft::tag<ft::const_qualified,ft::volatile_qualified> >
+ ));
+
+ BOOST_MPL_ASSERT_NOT((
+ ft::is_function<T, ft::non_const >
+ ));
+
+ BOOST_MPL_ASSERT_NOT((
+ ft::is_function<T, ft::non_volatile >
+ ));
+
+ BOOST_MPL_ASSERT_NOT((
+ ft::is_function<T, ft::tag<ft::non_const,ft::non_volatile> >
+ ));
+}
+
+
+struct C
+{
+ void non_cv(int) { }
+ void c_non_v(int) const { }
+ void v_non_c(int) volatile { }
+ void cv(int) const volatile { }
+};
+
+void instanitate()
+{
+ test_non_cv(& C::non_cv);
+ test_c_non_v(& C::c_non_v);
+ test_v_non_c(& C::v_non_c);
+ test_cv(& C::cv);
+}
+
diff --git a/src/boost/libs/function_types/test/classification/is_cv_mem_func_ptr.cpp b/src/boost/libs/function_types/test/classification/is_cv_mem_func_ptr.cpp
new file mode 100644
index 000000000..0b75c43d5
--- /dev/null
+++ b/src/boost/libs/function_types/test/classification/is_cv_mem_func_ptr.cpp
@@ -0,0 +1,150 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/function_types/is_member_function_pointer.hpp>
+
+namespace ft = boost::function_types;
+
+class C;
+typedef void (C::*mem_func_ptr)();
+typedef void (C::*c_mem_func_ptr)() const;
+typedef void (C::*v_mem_func_ptr)() volatile;
+typedef void (C::*cv_mem_func_ptr)() const volatile;
+
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< mem_func_ptr, ft::non_const >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< mem_func_ptr, ft::non_volatile >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< mem_func_ptr,
+ ft::tag<ft::non_const, ft::non_volatile> >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< mem_func_ptr, ft::const_qualified >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< mem_func_ptr, ft::volatile_qualified >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< mem_func_ptr,
+ ft::tag<ft::const_qualified, ft::volatile_qualified> >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< mem_func_ptr,
+ ft::tag<ft::non_const, ft::volatile_qualified> >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< mem_func_ptr,
+ ft::tag<ft::const_qualified, ft::non_volatile> >
+));
+
+//
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< c_mem_func_ptr, ft::const_qualified >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< c_mem_func_ptr, ft::non_volatile >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< c_mem_func_ptr, ft::non_const >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< c_mem_func_ptr, ft::volatile_qualified >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< c_mem_func_ptr,
+ ft::tag<ft::const_qualified, ft::non_volatile> >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< c_mem_func_ptr,
+ ft::tag<ft::non_const, ft::volatile_qualified> >
+));
+
+//
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< v_mem_func_ptr, ft::volatile_qualified >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< v_mem_func_ptr, ft::non_const >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< v_mem_func_ptr, ft::non_volatile >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< v_mem_func_ptr, ft::const_qualified >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< v_mem_func_ptr,
+ ft::tag<ft::non_const, ft::volatile_qualified> >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< v_mem_func_ptr,
+ ft::tag<ft::const_qualified, ft::non_volatile> >
+));
+
+//
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< cv_mem_func_ptr, ft::const_qualified >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< cv_mem_func_ptr, ft::volatile_qualified >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< cv_mem_func_ptr, ft::non_const >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< cv_mem_func_ptr, ft::non_volatile >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< cv_mem_func_ptr,
+ ft::tag<ft::non_const, ft::non_volatile> >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< cv_mem_func_ptr,
+ ft::tag<ft::const_qualified, ft::non_volatile> >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< cv_mem_func_ptr,
+ ft::tag<ft::non_const, ft::volatile_qualified> >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< cv_mem_func_ptr,
+ ft::tag<ft::const_qualified, ft::volatile_qualified> >
+));
+
diff --git a/src/boost/libs/function_types/test/classification/is_cv_pointer.cpp b/src/boost/libs/function_types/test/classification/is_cv_pointer.cpp
new file mode 100644
index 000000000..383052ee7
--- /dev/null
+++ b/src/boost/libs/function_types/test/classification/is_cv_pointer.cpp
@@ -0,0 +1,50 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/function_types/is_function_pointer.hpp>
+#include <boost/function_types/is_member_function_pointer.hpp>
+
+namespace ft = boost::function_types;
+
+typedef void(* const func_c_ptr)();
+typedef void(* volatile func_v_ptr)();
+typedef void(* const volatile func_cv_ptr)();
+class C;
+typedef void(C::* const mem_func_c_ptr)();
+typedef void(C::* volatile mem_func_v_ptr)();
+typedef void(C::* const volatile mem_func_cv_ptr)();
+
+// note: the pointer has cv-qualifiers, not the function - non_cv tag must match
+
+BOOST_MPL_ASSERT((
+ ft::is_function_pointer< func_c_ptr, ft::non_cv >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_function_pointer< func_v_ptr, ft::non_cv >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_function_pointer< func_cv_ptr, ft::non_cv >
+));
+
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< mem_func_c_ptr, ft::non_cv >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< mem_func_v_ptr, ft::non_cv >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< mem_func_cv_ptr, ft::non_cv >
+));
+
+
diff --git a/src/boost/libs/function_types/test/classification/is_function.cpp b/src/boost/libs/function_types/test/classification/is_function.cpp
new file mode 100644
index 000000000..9c6a35748
--- /dev/null
+++ b/src/boost/libs/function_types/test/classification/is_function.cpp
@@ -0,0 +1,87 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/function_types/is_function.hpp>
+
+namespace ft = boost::function_types;
+
+typedef void func();
+typedef void (*func_ptr)();
+typedef void (&func_ref)();
+class C;
+typedef void (C::*mem_func_ptr)();
+typedef void (C::*c_mem_func_ptr)() const;
+typedef void (C::*v_mem_func_ptr)() volatile;
+typedef void (C::*cv_mem_func_ptr)() const volatile;
+
+
+BOOST_MPL_ASSERT((
+ ft::is_function< func >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< func_ref >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< c_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< v_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< cv_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< mem_func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< C >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< int >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< int* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< int** >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< int& >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< int[] >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function< int[1] >
+));
+
diff --git a/src/boost/libs/function_types/test/classification/is_function_pointer.cpp b/src/boost/libs/function_types/test/classification/is_function_pointer.cpp
new file mode 100644
index 000000000..54ef29fe1
--- /dev/null
+++ b/src/boost/libs/function_types/test/classification/is_function_pointer.cpp
@@ -0,0 +1,87 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/function_types/is_function_pointer.hpp>
+
+namespace ft = boost::function_types;
+
+typedef void func();
+typedef void (*func_ptr)();
+typedef void (&func_ref)();
+class C;
+typedef void (C::*mem_func_ptr)();
+typedef void (C::*c_mem_func_ptr)() const;
+typedef void (C::*v_mem_func_ptr)() volatile;
+typedef void (C::*cv_mem_func_ptr)() const volatile;
+
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< func >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_function_pointer< func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< func_ref >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< c_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< v_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< cv_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< mem_func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< C >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< int >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< int* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< int** >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< int& >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< int[] >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_pointer< int[1] >
+));
+
diff --git a/src/boost/libs/function_types/test/classification/is_function_reference.cpp b/src/boost/libs/function_types/test/classification/is_function_reference.cpp
new file mode 100644
index 000000000..2f8f006fd
--- /dev/null
+++ b/src/boost/libs/function_types/test/classification/is_function_reference.cpp
@@ -0,0 +1,88 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/function_types/is_function_reference.hpp>
+
+namespace ft = boost::function_types;
+
+typedef void func();
+typedef void (*func_ptr)();
+typedef void (&func_ref)();
+class C;
+typedef void (C::*mem_func_ptr)();
+typedef void (C::*c_mem_func_ptr)() const;
+typedef void (C::*v_mem_func_ptr)() volatile;
+typedef void (C::*cv_mem_func_ptr)() const volatile;
+
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< func >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_function_reference< func_ref >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< c_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< v_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< cv_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< mem_func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< C >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< int >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< int* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< int** >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< int& >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< int[] >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_function_reference< int[1] >
+));
+
+
diff --git a/src/boost/libs/function_types/test/classification/is_member_function_pointer.cpp b/src/boost/libs/function_types/test/classification/is_member_function_pointer.cpp
new file mode 100644
index 000000000..0548c37f7
--- /dev/null
+++ b/src/boost/libs/function_types/test/classification/is_member_function_pointer.cpp
@@ -0,0 +1,96 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/function_types/is_member_function_pointer.hpp>
+
+namespace ft = boost::function_types;
+
+typedef void func();
+typedef void (*func_ptr)();
+typedef void (&func_ref)();
+class C;
+typedef void (C::*mem_func_ptr)();
+typedef void (C::*c_mem_func_ptr)() const;
+typedef void (C::*v_mem_func_ptr)() volatile;
+typedef void (C::*cv_mem_func_ptr)() const volatile;
+typedef int C::*mem_ptr;
+
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< func >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< func_ref >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< c_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< v_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_function_pointer< cv_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< mem_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< mem_func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< mem_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< C >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< int >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< int* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< int** >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< int& >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< int[] >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_function_pointer< int[1] >
+));
+
diff --git a/src/boost/libs/function_types/test/classification/is_member_object_pointer.cpp b/src/boost/libs/function_types/test/classification/is_member_object_pointer.cpp
new file mode 100644
index 000000000..840832714
--- /dev/null
+++ b/src/boost/libs/function_types/test/classification/is_member_object_pointer.cpp
@@ -0,0 +1,95 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/function_types/is_member_object_pointer.hpp>
+
+namespace ft = boost::function_types;
+
+typedef void func();
+typedef void (*func_ptr)();
+typedef void (&func_ref)();
+class C;
+typedef void (C::*mem_func_ptr)();
+typedef void (C::*c_mem_func_ptr)() const;
+typedef void (C::*v_mem_func_ptr)() volatile;
+typedef void (C::*cv_mem_func_ptr)() const volatile;
+typedef int C::*mem_ptr;
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< func >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< func_ref >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< c_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< v_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< cv_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_object_pointer< mem_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< mem_func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< mem_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< C >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< int >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< int* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< int** >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< int& >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< int[] >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_object_pointer< int[1] >
+));
+
diff --git a/src/boost/libs/function_types/test/classification/is_member_pointer.cpp b/src/boost/libs/function_types/test/classification/is_member_pointer.cpp
new file mode 100644
index 000000000..113902737
--- /dev/null
+++ b/src/boost/libs/function_types/test/classification/is_member_pointer.cpp
@@ -0,0 +1,88 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/function_types/is_member_pointer.hpp>
+
+namespace ft = boost::function_types;
+
+typedef void func();
+typedef void (*func_ptr)();
+typedef void (&func_ref)();
+class C;
+typedef void (C::*mem_func_ptr)();
+typedef void (C::*c_mem_func_ptr)() const;
+typedef void (C::*v_mem_func_ptr)() volatile;
+typedef void (C::*cv_mem_func_ptr)() const volatile;
+typedef int C::*mem_ptr;
+
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_pointer< func >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_pointer< func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_pointer< func_ref >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_pointer< mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_pointer< c_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_pointer< v_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_pointer< cv_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_member_pointer< mem_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_pointer< func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_pointer< mem_func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_pointer< mem_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_pointer< C >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_pointer< int >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_pointer< int* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_pointer< int** >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_member_pointer< int& >
+));
+
diff --git a/src/boost/libs/function_types/test/classification/is_nonmember_callable_builtin.cpp b/src/boost/libs/function_types/test/classification/is_nonmember_callable_builtin.cpp
new file mode 100644
index 000000000..902d6ee3b
--- /dev/null
+++ b/src/boost/libs/function_types/test/classification/is_nonmember_callable_builtin.cpp
@@ -0,0 +1,87 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/function_types/is_nonmember_callable_builtin.hpp>
+
+namespace ft = boost::function_types;
+
+typedef void func();
+typedef void (*func_ptr)();
+typedef void (&func_ref)();
+class C;
+typedef void (C::*mem_func_ptr)();
+typedef void (C::*c_mem_func_ptr)() const;
+typedef void (C::*v_mem_func_ptr)() volatile;
+typedef void (C::*cv_mem_func_ptr)() const volatile;
+
+
+BOOST_MPL_ASSERT((
+ ft::is_nonmember_callable_builtin< func >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_nonmember_callable_builtin< func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_nonmember_callable_builtin< func_ref >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_nonmember_callable_builtin< mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_nonmember_callable_builtin< c_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_nonmember_callable_builtin< v_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_nonmember_callable_builtin< cv_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_nonmember_callable_builtin< func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_nonmember_callable_builtin< mem_func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_nonmember_callable_builtin< C >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_nonmember_callable_builtin< int >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_nonmember_callable_builtin< int* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_nonmember_callable_builtin< int** >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_nonmember_callable_builtin< int& >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_nonmember_callable_builtin< int[] >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_nonmember_callable_builtin< int[1] >
+));
+
diff --git a/src/boost/libs/function_types/test/classification/is_variadic.cpp b/src/boost/libs/function_types/test/classification/is_variadic.cpp
new file mode 100644
index 000000000..964ea8c56
--- /dev/null
+++ b/src/boost/libs/function_types/test/classification/is_variadic.cpp
@@ -0,0 +1,143 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/function_types/is_callable_builtin.hpp>
+
+namespace ft = boost::function_types;
+
+typedef void func(...);
+typedef void nv_func();
+typedef void (*func_ptr)(...);
+typedef void (*nv_func_ptr)();
+typedef void (&func_ref)(...);
+typedef void (&nv_func_ref)();
+class C;
+typedef void (C::*mem_func_ptr)(...);
+typedef void (C::*nv_mem_func_ptr)();
+typedef void (C::*c_mem_func_ptr)(...) const;
+typedef void (C::*v_mem_func_ptr)(...) volatile;
+typedef void (C::*cv_mem_func_ptr)(...) const volatile;
+typedef int C::* mem_ptr;
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< func >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< func, ft::variadic >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< func, ft::non_variadic >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< nv_func >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< nv_func, ft::variadic >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< nv_func, ft::non_variadic >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< func_ptr, ft::variadic>
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< func_ptr, ft::non_variadic >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< nv_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< nv_func_ptr, ft::variadic>
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< nv_func_ptr, ft::non_variadic >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< func_ref >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< mem_func_ptr, ft::variadic >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< mem_func_ptr, ft::non_variadic >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< nv_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< nv_mem_func_ptr, ft::variadic >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< nv_mem_func_ptr, ft::non_variadic >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< c_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< v_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< cv_mem_func_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< mem_func_ptr* >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< C, ft::variadic >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< C, ft::non_variadic >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< mem_ptr >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< mem_ptr, ft::variadic >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< mem_ptr, ft::non_variadic >
+));
+
diff --git a/src/boost/libs/function_types/test/custom_ccs/member_ccs.cpp b/src/boost/libs/function_types/test/custom_ccs/member_ccs.cpp
new file mode 100644
index 000000000..11f939268
--- /dev/null
+++ b/src/boost/libs/function_types/test/custom_ccs/member_ccs.cpp
@@ -0,0 +1,50 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#define BOOST_FT_AUTODETECT_CALLING_CONVENTIONS
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/function_types/member_function_pointer.hpp>
+#include <boost/function_types/is_callable_builtin.hpp>
+
+#ifndef BOOST_FT_CC_STDCALL
+# error "test not supported with this compiler/platform"
+#endif
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+
+typedef ft::stdcall_cc cc;
+
+class C;
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin<
+ ft::member_function_pointer<mpl::vector<int, C &>, cc>::type
+ >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin<
+ ft::member_function_pointer<mpl::vector<int, C const &>, cc>::type
+ >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin<
+ ft::member_function_pointer<mpl::vector<int, C volatile &>, cc>::type
+ >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin<
+ ft::member_function_pointer<mpl::vector<int, C const volatile &>, cc>::type
+ >
+));
+
diff --git a/src/boost/libs/function_types/test/custom_ccs/member_ccs_exact.cpp b/src/boost/libs/function_types/test/custom_ccs/member_ccs_exact.cpp
new file mode 100644
index 000000000..413b1334a
--- /dev/null
+++ b/src/boost/libs/function_types/test/custom_ccs/member_ccs_exact.cpp
@@ -0,0 +1,71 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#define BOOST_FT_AUTODETECT_CALLING_CONVENTIONS
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/function_types/member_function_pointer.hpp>
+#include <boost/function_types/is_callable_builtin.hpp>
+
+#ifndef BOOST_FT_CC_STDCALL
+# error "test not supported with this compiler/platform"
+#endif
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+
+typedef ft::stdcall_cc cc;
+typedef ft::default_cc dc;
+
+class C;
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< ft::member_function_pointer<mpl::vector<int, C &>, cc>::type, cc >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< ft::member_function_pointer<mpl::vector<int, C const &>, cc>::type, cc >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< ft::member_function_pointer<mpl::vector<int, C volatile &>, cc>::type, cc >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< ft::member_function_pointer<mpl::vector<int, C const volatile &>, cc>::type, cc >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< ft::member_function_pointer<mpl::vector<int, C &> >::type, dc >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< ft::member_function_pointer<mpl::vector<int, C &>, cc>::type, dc >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< ft::member_function_pointer<mpl::vector<int, C const &>, cc>::type, dc >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< ft::member_function_pointer<mpl::vector<int, C volatile &>, cc>::type, dc >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< ft::member_function_pointer<mpl::vector<int, C const volatile &>, cc>::type, dc >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< ft::member_function_pointer<mpl::vector<int, C &> >::type, cc >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< ft::member_function_pointer<mpl::vector<int, C &>, cc>::type, dc >
+));
+
diff --git a/src/boost/libs/function_types/test/custom_ccs/nonmember_ccs.cpp b/src/boost/libs/function_types/test/custom_ccs/nonmember_ccs.cpp
new file mode 100644
index 000000000..81681ff02
--- /dev/null
+++ b/src/boost/libs/function_types/test/custom_ccs/nonmember_ccs.cpp
@@ -0,0 +1,45 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#define BOOST_FT_AUTODETECT_CALLING_CONVENTIONS
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/function_types/function_type.hpp>
+#include <boost/function_types/function_pointer.hpp>
+#include <boost/function_types/function_reference.hpp>
+#include <boost/function_types/is_callable_builtin.hpp>
+
+#ifndef BOOST_FT_CC_STDCALL
+# error "test not supported with this compiler/platform"
+#endif
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+
+typedef ft::stdcall_cc cc;
+
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin<
+ ft::function_type<mpl::vector<void,int>, cc>::type
+ >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin<
+ ft::function_pointer<mpl::vector<void,int>, cc>::type
+ >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin<
+ ft::function_reference<mpl::vector<void,int>, cc>::type
+ >
+));
+
diff --git a/src/boost/libs/function_types/test/custom_ccs/nonmember_ccs_exact.cpp b/src/boost/libs/function_types/test/custom_ccs/nonmember_ccs_exact.cpp
new file mode 100644
index 000000000..d6db30024
--- /dev/null
+++ b/src/boost/libs/function_types/test/custom_ccs/nonmember_ccs_exact.cpp
@@ -0,0 +1,62 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#define BOOST_FT_AUTODETECT_CALLING_CONVENTIONS
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/function_types/function_type.hpp>
+#include <boost/function_types/function_pointer.hpp>
+#include <boost/function_types/function_reference.hpp>
+#include <boost/function_types/is_callable_builtin.hpp>
+
+#ifndef BOOST_FT_CC_STDCALL
+# error "test not supported with this compiler/platform"
+#endif
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+
+typedef ft::stdcall_cc cc;
+typedef ft::default_cc dc;
+
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< ft::function_type<mpl::vector<void>,cc>::type, cc >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< ft::function_pointer<mpl::vector<void>,cc>::type, cc >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< ft::function_reference<mpl::vector<void>,cc>::type, cc >
+));
+
+BOOST_MPL_ASSERT((
+ ft::is_callable_builtin< ft::function_pointer<mpl::vector<void> >::type, dc >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< ft::function_type<mpl::vector<void>, cc>::type, dc >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< ft::function_pointer<mpl::vector<void>,cc>::type, dc >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< ft::function_reference<mpl::vector<void>,cc>::type, dc >
+));
+
+BOOST_MPL_ASSERT_NOT((
+ ft::is_callable_builtin< ft::function_pointer<mpl::vector<void> >::type, cc >
+));
+
+
+
diff --git a/src/boost/libs/function_types/test/custom_ccs/property_tag.cpp b/src/boost/libs/function_types/test/custom_ccs/property_tag.cpp
new file mode 100644
index 000000000..00d241942
--- /dev/null
+++ b/src/boost/libs/function_types/test/custom_ccs/property_tag.cpp
@@ -0,0 +1,64 @@
+
+// (C) Copyright Edward Diener 2019
+// Use, modification and distribution are subject to 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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/function_types/property_tags.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+
+typedef ft::tag<ft::variadic,ft::non_volatile,ft::non_const,ft::default_cc> tag1;
+typedef ft::tag<ft::const_non_volatile,ft::const_qualified> tag2;
+typedef ft::tag<ft::cv_qualified,ft::variadic> tag3;
+typedef ft::null_tag tag4;
+typedef ft::tag<ft::variadic,ft::volatile_non_const> tag5;
+typedef ft::tag<ft::volatile_qualified,ft::non_const,ft::variadic> tag6;
+typedef ft::tag<ft::non_variadic,ft::const_non_volatile,ft::default_cc> tag7;
+typedef ft::tag<ft::non_cv,ft::default_cc> tag8;
+
+BOOST_MPL_ASSERT((ft::has_property_tag<tag1, ft::variadic>));
+BOOST_MPL_ASSERT((ft::has_property_tag<tag2, ft::const_qualified>));
+BOOST_MPL_ASSERT((ft::has_property_tag<tag3, ft::cv_qualified>));
+BOOST_MPL_ASSERT((ft::has_property_tag<tag4, ft::null_tag>));
+BOOST_MPL_ASSERT((ft::has_property_tag<tag5, ft::volatile_qualified>));
+BOOST_MPL_ASSERT((ft::has_property_tag<tag6, ft::volatile_qualified>));
+BOOST_MPL_ASSERT((ft::has_property_tag<tag7, ft::const_qualified>));
+BOOST_MPL_ASSERT((ft::has_property_tag<tag8, ft::default_cc>));
+
+BOOST_MPL_ASSERT((ft::has_variadic_property_tag<tag1>));
+BOOST_MPL_ASSERT((ft::has_variadic_property_tag<tag3>));
+BOOST_MPL_ASSERT((ft::has_variadic_property_tag<tag5>));
+BOOST_MPL_ASSERT((ft::has_variadic_property_tag<tag6>));
+BOOST_MPL_ASSERT((ft::has_default_cc_property_tag<tag1>));
+BOOST_MPL_ASSERT((ft::has_default_cc_property_tag<tag7>));
+BOOST_MPL_ASSERT((ft::has_default_cc_property_tag<tag8>));
+BOOST_MPL_ASSERT((ft::has_const_property_tag<tag2>));
+BOOST_MPL_ASSERT((ft::has_const_property_tag<tag3>));
+BOOST_MPL_ASSERT((ft::has_const_property_tag<tag7>));
+BOOST_MPL_ASSERT((ft::has_volatile_property_tag<tag3>));
+BOOST_MPL_ASSERT((ft::has_volatile_property_tag<tag5>));
+BOOST_MPL_ASSERT((ft::has_volatile_property_tag<tag6>));
+BOOST_MPL_ASSERT((ft::has_cv_property_tag<tag3>));
+BOOST_MPL_ASSERT((ft::has_null_property_tag<tag4>));
+
+BOOST_MPL_ASSERT_NOT((ft::has_property_tag<tag1, ft::const_qualified>));
+BOOST_MPL_ASSERT_NOT((ft::has_property_tag<tag2, ft::cv_qualified>));
+BOOST_MPL_ASSERT_NOT((ft::has_property_tag<tag3, ft::null_tag>));
+BOOST_MPL_ASSERT_NOT((ft::has_property_tag<tag4, ft::volatile_qualified>));
+BOOST_MPL_ASSERT_NOT((ft::has_property_tag<tag5, ft::const_qualified>));
+BOOST_MPL_ASSERT_NOT((ft::has_property_tag<tag6, ft::default_cc>));
+BOOST_MPL_ASSERT_NOT((ft::has_property_tag<tag7, ft::variadic>));
+BOOST_MPL_ASSERT_NOT((ft::has_property_tag<tag8, ft::volatile_qualified>));
+
+BOOST_MPL_ASSERT_NOT((ft::has_variadic_property_tag<tag2>));
+BOOST_MPL_ASSERT_NOT((ft::has_default_cc_property_tag<tag6>));
+BOOST_MPL_ASSERT_NOT((ft::has_const_property_tag<tag4>));
+BOOST_MPL_ASSERT_NOT((ft::has_const_property_tag<tag5>));
+BOOST_MPL_ASSERT_NOT((ft::has_volatile_property_tag<tag7>));
+BOOST_MPL_ASSERT_NOT((ft::has_cv_property_tag<tag1>));
+BOOST_MPL_ASSERT_NOT((ft::has_null_property_tag<tag8>));
diff --git a/src/boost/libs/function_types/test/decomposition/class_type_transform.cpp b/src/boost/libs/function_types/test/decomposition/class_type_transform.cpp
new file mode 100644
index 000000000..f007a40c7
--- /dev/null
+++ b/src/boost/libs/function_types/test/decomposition/class_type_transform.cpp
@@ -0,0 +1,62 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/add_pointer.hpp>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/mpl/always.hpp>
+
+#include <boost/function_types/components.hpp>
+#include <boost/function_types/parameter_types.hpp>
+
+using namespace boost;
+namespace ft = function_types;
+using boost::mpl::placeholders::_;
+
+class C;
+typedef C (C::*mem_func_ptr)();
+class X;
+
+BOOST_MPL_ASSERT((
+ is_same< mpl::at_c<
+ ft::components<mem_func_ptr, add_pointer<_> >
+ ,1 >::type, C* >
+));
+BOOST_MPL_ASSERT((
+ is_same< mpl::at_c<
+ ft::components<mem_func_ptr, add_pointer< add_pointer<_> > >
+ ,1 >::type, C** >
+));
+BOOST_MPL_ASSERT((
+ is_same< mpl::at_c<
+ ft::components<mem_func_ptr, mpl::always<X> >
+ ,1 >::type, X >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< mpl::at_c<
+ ft::parameter_types<mem_func_ptr, add_pointer<_> >
+ ,0 >::type, C* >
+));
+BOOST_MPL_ASSERT((
+ is_same< mpl::at_c<
+ ft::parameter_types<mem_func_ptr, add_pointer< add_pointer<_> > >
+ ,0 >::type, C** >
+));
+BOOST_MPL_ASSERT((
+ is_same< mpl::at_c<
+ ft::parameter_types<mem_func_ptr, mpl::always<X> >
+ ,0 >::type, X >
+));
+
+
+
+
diff --git a/src/boost/libs/function_types/test/decomposition/components.cpp b/src/boost/libs/function_types/test/decomposition/components.cpp
new file mode 100644
index 000000000..60cebde3d
--- /dev/null
+++ b/src/boost/libs/function_types/test/decomposition/components.cpp
@@ -0,0 +1,59 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/equal.hpp>
+
+#include <boost/function_types/components.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+
+class C;
+typedef C func();
+typedef C (*func_ptr)(int);
+typedef C (&func_ref)(int,int);
+typedef C (C::*mem_func_ptr)();
+typedef C (C::*c_mem_func_ptr)(int) const;
+typedef C (C::*v_mem_func_ptr)(int,int) volatile;
+typedef C (C::*cv_mem_func_ptr)(int,int,int) const volatile;
+typedef int C::* mem_ptr;
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::components<func>::types, mpl::vector<C> >
+));
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::components<func_ptr>::types, mpl::vector<C,int> >
+));
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::components<func_ref>::types, mpl::vector<C,int,int> >
+));
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::components<mem_func_ptr>::types, mpl::vector<C,C &> >
+));
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::components<c_mem_func_ptr>::types, mpl::vector<C,C const &,int> >
+));
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::components<v_mem_func_ptr>::types, mpl::vector<C,C volatile &,int,int> >
+));
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::components<cv_mem_func_ptr>::types, mpl::vector<C,C const volatile &,int,int,int> >
+));
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::components<mem_ptr>::types, mpl::vector<int &,C&> >
+));
+
diff --git a/src/boost/libs/function_types/test/decomposition/components_seq.cpp b/src/boost/libs/function_types/test/decomposition/components_seq.cpp
new file mode 100644
index 000000000..ad5f5900c
--- /dev/null
+++ b/src/boost/libs/function_types/test/decomposition/components_seq.cpp
@@ -0,0 +1,75 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/equal.hpp>
+
+#include <boost/mpl/front.hpp>
+#include <boost/mpl/back.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/begin_end.hpp>
+#include <boost/mpl/clear.hpp>
+#include <boost/mpl/push_front.hpp>
+#include <boost/mpl/pop_front.hpp>
+#include <boost/mpl/push_back.hpp>
+#include <boost/mpl/pop_back.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/empty.hpp>
+
+#include <boost/function_types/components.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+using boost::is_same;
+
+class C;
+typedef C (C::* mem_func_ptr)(int);
+typedef ft::components<mem_func_ptr> c;
+
+
+// front
+BOOST_MPL_ASSERT(( is_same< ::boost::mpl::front<c>::type, C > ));
+
+// back
+BOOST_MPL_ASSERT(( is_same< ::boost::mpl::back<c>::type, int > ));
+
+// at
+BOOST_MPL_ASSERT(( is_same< ::boost::mpl::at_c<c,0>::type, C > ));
+BOOST_MPL_ASSERT(( is_same< ::boost::mpl::at_c<c,1>::type, C & > ));
+BOOST_MPL_ASSERT(( is_same< ::boost::mpl::at_c<c,2>::type, int > ));
+
+// begin/end
+BOOST_MPL_ASSERT(( mpl::equal< c, mpl::vector<C,C &, int> > ));
+
+
+// clear
+BOOST_MPL_ASSERT(( mpl::equal< mpl::clear<c>, mpl::vector<> > ));
+
+// push_front
+BOOST_MPL_ASSERT(( mpl::equal< mpl::push_front<c,C>::type, mpl::vector<C,C,C &,int> > ));
+
+// pop_front
+BOOST_MPL_ASSERT(( mpl::equal< mpl::pop_front<c>::type, mpl::vector<C &,int> > ));
+
+// push_back
+BOOST_MPL_ASSERT(( mpl::equal< mpl::push_back<c,C>::type, mpl::vector<C,C &,int,C> > ));
+
+// pop_back
+BOOST_MPL_ASSERT(( mpl::equal< mpl::pop_back<c>::type, mpl::vector<C,C &> > ));
+
+
+// size
+BOOST_MPL_ASSERT_RELATION( ::boost::mpl::size<c>::value, ==, 3 );
+
+// empty
+BOOST_MPL_ASSERT_NOT(( mpl::empty<c> ));
+BOOST_MPL_ASSERT(( mpl::empty< mpl::clear<c> > ));
+
diff --git a/src/boost/libs/function_types/test/decomposition/function_arity.cpp b/src/boost/libs/function_types/test/decomposition/function_arity.cpp
new file mode 100644
index 000000000..219c2c6ef
--- /dev/null
+++ b/src/boost/libs/function_types/test/decomposition/function_arity.cpp
@@ -0,0 +1,31 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+
+#include <boost/function_types/function_arity.hpp>
+
+class C;
+typedef C func();
+typedef C (*func_ptr)(int);
+typedef C (&func_ref)(int,int);
+typedef C (C::*mem_func_ptr)();
+typedef C (C::*c_mem_func_ptr)(int) const;
+typedef C (C::*v_mem_func_ptr)(int,int) volatile;
+typedef C (C::*cv_mem_func_ptr)(int,int,int) const volatile;
+typedef int C::* mem_ptr;
+
+BOOST_MPL_ASSERT_RELATION( ::boost::function_types::function_arity<func>::value, ==, 0 );
+BOOST_MPL_ASSERT_RELATION( ::boost::function_types::function_arity<func_ptr>::value, ==, 1 );
+BOOST_MPL_ASSERT_RELATION( ::boost::function_types::function_arity<func_ref>::value, ==, 2 );
+BOOST_MPL_ASSERT_RELATION( ::boost::function_types::function_arity<mem_func_ptr>::value, ==, 1 );
+BOOST_MPL_ASSERT_RELATION( ::boost::function_types::function_arity<c_mem_func_ptr>::value, ==, 2 );
+BOOST_MPL_ASSERT_RELATION( ::boost::function_types::function_arity<v_mem_func_ptr>::value, ==, 3 );
+BOOST_MPL_ASSERT_RELATION( ::boost::function_types::function_arity<cv_mem_func_ptr>::value, ==, 4 );
+BOOST_MPL_ASSERT_RELATION( ::boost::function_types::function_arity<mem_ptr>::value, ==, 1 );
+
diff --git a/src/boost/libs/function_types/test/decomposition/function_arity_fail.cpp b/src/boost/libs/function_types/test/decomposition/function_arity_fail.cpp
new file mode 100644
index 000000000..39a7c7409
--- /dev/null
+++ b/src/boost/libs/function_types/test/decomposition/function_arity_fail.cpp
@@ -0,0 +1,19 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/function_types/function_arity.hpp>
+
+
+namespace ft = boost::function_types;
+
+class C;
+
+typedef ft::function_arity<C>::type error_1;
+typedef ft::function_arity<int>::type error_2;
+typedef ft::function_arity<void>::type error_3;
+
diff --git a/src/boost/libs/function_types/test/decomposition/parameter_types.cpp b/src/boost/libs/function_types/test/decomposition/parameter_types.cpp
new file mode 100644
index 000000000..5feb1a886
--- /dev/null
+++ b/src/boost/libs/function_types/test/decomposition/parameter_types.cpp
@@ -0,0 +1,59 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/equal.hpp>
+
+#include <boost/function_types/parameter_types.hpp>
+
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+
+class C;
+typedef C func(C);
+typedef C (*func_ptr)(C,int);
+typedef C (&func_ref)();
+typedef C (C::*mem_func_ptr)(C,int);
+typedef C (C::*c_mem_func_ptr)(C,C) const;
+typedef C (C::*v_mem_func_ptr)(C) volatile;
+typedef C (C::*cv_mem_func_ptr)() const volatile;
+typedef C C::*mem_ptr;
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::parameter_types<func>, mpl::vector<C> >
+));
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::parameter_types<func_ptr>::type, mpl::vector<C,int> >
+));
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::parameter_types<func_ref>, mpl::vector<> >
+));
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::parameter_types<mem_func_ptr>, mpl::vector<C &,C,int> >
+));
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::parameter_types<c_mem_func_ptr>, mpl::vector<C const &,C,C> >
+));
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::parameter_types<v_mem_func_ptr>, mpl::vector<C volatile &,C> >
+));
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::parameter_types<cv_mem_func_ptr>, mpl::vector<C const volatile &> >
+));
+
+BOOST_MPL_ASSERT((
+ mpl::equal< ft::parameter_types<mem_ptr>, mpl::vector<C &> >
+));
diff --git a/src/boost/libs/function_types/test/decomposition/parameter_types_fail.cpp b/src/boost/libs/function_types/test/decomposition/parameter_types_fail.cpp
new file mode 100644
index 000000000..d23e8911b
--- /dev/null
+++ b/src/boost/libs/function_types/test/decomposition/parameter_types_fail.cpp
@@ -0,0 +1,19 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/function_types/parameter_types.hpp>
+
+
+namespace ft = boost::function_types;
+
+class C;
+
+typedef ft::parameter_types<C>::type error_1;
+typedef ft::parameter_types<char>::type error_2;
+typedef ft::parameter_types<void>::type error_3;
+
diff --git a/src/boost/libs/function_types/test/decomposition/result_type.cpp b/src/boost/libs/function_types/test/decomposition/result_type.cpp
new file mode 100644
index 000000000..f55eb854d
--- /dev/null
+++ b/src/boost/libs/function_types/test/decomposition/result_type.cpp
@@ -0,0 +1,98 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/function_types/result_type.hpp>
+
+
+namespace ft = boost::function_types;
+
+class C;
+typedef C func();
+typedef C const c_func();
+typedef C (*func_ptr)();
+typedef C const (*c_func_ptr)();
+typedef C (&func_ref)();
+typedef C const (&c_func_ref)();
+typedef C (C::*mem_func_ptr)();
+typedef C const (C::*c_mem_func_ptr)();
+typedef C (C::*mem_func_ptr_c)() const;
+typedef C const (C::*c_mem_func_ptr_c)() const;
+typedef C (C::*mem_func_ptr_v)() volatile;
+typedef C const (C::*c_mem_func_ptr_v)() volatile;
+typedef C (C::*mem_func_ptr_cv)() const volatile;
+typedef C const (C::*c_mem_func_ptr_cv)() const volatile;
+typedef int C::* mem_ptr;
+typedef int const C::* c_mem_ptr;
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<func>::type,C>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<c_func>::type,C const>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<func_ptr>::type,C>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<c_func_ptr>::type,C const>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<func_ref>::type,C>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<c_func_ref>::type,C const>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<mem_func_ptr>::type,C>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<c_mem_func_ptr>::type,C const>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<mem_func_ptr_c>::type,C>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<c_mem_func_ptr_c>::type,C const>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<mem_func_ptr_v>::type,C>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<c_mem_func_ptr_v>::type,C const>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<mem_func_ptr_cv>::type,C>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<c_mem_func_ptr_cv>::type,C const>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<mem_ptr>::type,int&>
+));
+
+BOOST_MPL_ASSERT((
+ boost::is_same<ft::result_type<c_mem_ptr>::type,int const&>
+));
+
diff --git a/src/boost/libs/function_types/test/decomposition/result_type_fail.cpp b/src/boost/libs/function_types/test/decomposition/result_type_fail.cpp
new file mode 100644
index 000000000..c701e5796
--- /dev/null
+++ b/src/boost/libs/function_types/test/decomposition/result_type_fail.cpp
@@ -0,0 +1,19 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/function_types/result_type.hpp>
+
+
+namespace ft = boost::function_types;
+
+class C;
+
+typedef ft::result_type<C>::type error_1;
+typedef ft::result_type<char>::type error_2;
+typedef ft::result_type<void>::type error_3;
+
diff --git a/src/boost/libs/function_types/test/reconfiguration/cc_preprocessing.cpp b/src/boost/libs/function_types/test/reconfiguration/cc_preprocessing.cpp
new file mode 100644
index 000000000..889645d14
--- /dev/null
+++ b/src/boost/libs/function_types/test/reconfiguration/cc_preprocessing.cpp
@@ -0,0 +1,11 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#define BOOST_FT_CC_PREPROCESSING 1
+#include "simple_test.hpp"
+
diff --git a/src/boost/libs/function_types/test/reconfiguration/partial_arity_preprocessing.cpp b/src/boost/libs/function_types/test/reconfiguration/partial_arity_preprocessing.cpp
new file mode 100644
index 000000000..bd58cf92a
--- /dev/null
+++ b/src/boost/libs/function_types/test/reconfiguration/partial_arity_preprocessing.cpp
@@ -0,0 +1,11 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#define BOOST_FT_MAX_ARITY 19
+#include "simple_test.hpp"
+
diff --git a/src/boost/libs/function_types/test/reconfiguration/preprocessing_mode.cpp b/src/boost/libs/function_types/test/reconfiguration/preprocessing_mode.cpp
new file mode 100644
index 000000000..d6601c4ec
--- /dev/null
+++ b/src/boost/libs/function_types/test/reconfiguration/preprocessing_mode.cpp
@@ -0,0 +1,11 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#define BOOST_FT_PREPROCESSING_MODE 1
+#include "simple_test.hpp"
+
diff --git a/src/boost/libs/function_types/test/reconfiguration/simple_test.hpp b/src/boost/libs/function_types/test/reconfiguration/simple_test.hpp
new file mode 100644
index 000000000..5b62a0bd5
--- /dev/null
+++ b/src/boost/libs/function_types/test/reconfiguration/simple_test.hpp
@@ -0,0 +1,51 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/equal.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/function_types/components.hpp>
+#include <boost/function_types/function_type.hpp>
+#include <boost/function_types/member_function_pointer.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+
+class C;
+typedef void func(C &);
+typedef int (C::* mem_func_ptr)(int);
+
+typedef ft::components<func> func_components;
+typedef ft::components<mem_func_ptr> mfp_components;
+
+BOOST_MPL_ASSERT((
+ mpl::equal< func_components::types, mpl::vector<void,C &> >
+));
+BOOST_MPL_ASSERT_RELATION(
+ ::func_components::function_arity::value, ==, 1
+);
+
+BOOST_MPL_ASSERT((
+ boost::is_same< ft::function_type< mpl::vector<void,C &> >::type, func >
+));
+
+
+BOOST_MPL_ASSERT((
+ mpl::equal< mfp_components::types, mpl::vector<int,C &,int> >
+));
+BOOST_MPL_ASSERT_RELATION(
+ ::mfp_components::function_arity::value, ==, 2
+);
+
+BOOST_MPL_ASSERT((
+ boost::is_same< ft::member_function_pointer< mpl::vector<int,C &,int> >::type, mem_func_ptr >
+));
+
+
diff --git a/src/boost/libs/function_types/test/synthesis/cv_function_synthesis.cpp b/src/boost/libs/function_types/test/synthesis/cv_function_synthesis.cpp
new file mode 100644
index 000000000..b80e8547e
--- /dev/null
+++ b/src/boost/libs/function_types/test/synthesis/cv_function_synthesis.cpp
@@ -0,0 +1,249 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/function_types/function_type.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+
+template<typename C, typename T>
+void test_non_cv(T C::*)
+{
+ BOOST_MPL_ASSERT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::non_const,ft::non_volatile> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::non_const >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::non_volatile >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::const_qualified,ft::non_volatile> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::const_qualified >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::non_const,ft::volatile_qualified> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT((
+ boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::volatile_qualified >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::const_qualified,ft::volatile_qualified> >::type
+ , T
+ >));
+}
+
+template<typename C, typename T>
+void test_c_non_v(T C::*)
+{
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::non_const,ft::non_volatile> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::non_const >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::non_volatile >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::const_qualified,ft::non_volatile> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::const_qualified >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::non_const,ft::volatile_qualified> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT((
+ boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::volatile_qualified >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::const_qualified,ft::volatile_qualified> >::type
+ , T
+ >));
+}
+
+template<typename C, typename T>
+void test_v_non_c(T C::*)
+{
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::non_const,ft::non_volatile> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::non_const >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::non_volatile >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::const_qualified,ft::non_volatile> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::const_qualified >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::non_const,ft::volatile_qualified> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT((
+ boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::volatile_qualified >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::const_qualified,ft::volatile_qualified> >::type
+ , T
+ >));
+}
+
+template<typename C, typename T>
+void test_cv(T C::*)
+{
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::non_const,ft::non_volatile> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::non_const >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::non_volatile >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::const_qualified,ft::non_volatile> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::const_qualified >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::non_const,ft::volatile_qualified> >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT_NOT((
+ boost::is_same<
+ ft::function_type< mpl::vector<void,int>, ft::volatile_qualified >::type
+ , T
+ >));
+
+ BOOST_MPL_ASSERT(( boost::is_same<
+ ft::function_type< mpl::vector<void,int>,
+ ft::tag<ft::const_qualified,ft::volatile_qualified> >::type
+ , T
+ >));
+}
+
+
+struct C
+{
+ void non_cv(int) { }
+ void c_non_v(int) const { }
+ void v_non_c(int) volatile { }
+ void cv(int) const volatile { }
+};
+
+void instanitate()
+{
+ test_non_cv(& C::non_cv);
+ test_c_non_v(& C::c_non_v);
+ test_v_non_c(& C::v_non_c);
+ test_cv(& C::cv);
+}
+
diff --git a/src/boost/libs/function_types/test/synthesis/function_pointer.cpp b/src/boost/libs/function_types/test/synthesis/function_pointer.cpp
new file mode 100644
index 000000000..115093487
--- /dev/null
+++ b/src/boost/libs/function_types/test/synthesis/function_pointer.cpp
@@ -0,0 +1,24 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/function_types/function_pointer.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+
+using boost::is_same;
+
+typedef int (* expected)(int,int);
+
+BOOST_MPL_ASSERT((
+ is_same< ft::function_pointer< mpl::vector<int,int,int> >::type, expected >
+));
+
diff --git a/src/boost/libs/function_types/test/synthesis/function_reference.cpp b/src/boost/libs/function_types/test/synthesis/function_reference.cpp
new file mode 100644
index 000000000..92fa714e3
--- /dev/null
+++ b/src/boost/libs/function_types/test/synthesis/function_reference.cpp
@@ -0,0 +1,24 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/function_types/function_reference.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+
+using boost::is_same;
+
+typedef int (& expected)(int);
+
+BOOST_MPL_ASSERT((
+ is_same< ft::function_reference< mpl::vector<int,int> >::type, expected >
+));
+
diff --git a/src/boost/libs/function_types/test/synthesis/function_type.cpp b/src/boost/libs/function_types/test/synthesis/function_type.cpp
new file mode 100644
index 000000000..bb08ce7f2
--- /dev/null
+++ b/src/boost/libs/function_types/test/synthesis/function_type.cpp
@@ -0,0 +1,23 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/function_types/function_type.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+using boost::is_same;
+
+typedef int expected(int,int);
+
+BOOST_MPL_ASSERT((
+ is_same< ft::function_type< mpl::vector<int,int,int> >::type, expected >
+));
+
diff --git a/src/boost/libs/function_types/test/synthesis/mem_func_ptr_cv1.cpp b/src/boost/libs/function_types/test/synthesis/mem_func_ptr_cv1.cpp
new file mode 100644
index 000000000..b1f70beee
--- /dev/null
+++ b/src/boost/libs/function_types/test/synthesis/mem_func_ptr_cv1.cpp
@@ -0,0 +1,94 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/function_types/member_function_pointer.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+using boost::is_same;
+
+class C;
+
+typedef int (C::* expected1)(int);
+typedef int (C::* expected2)(int) const;
+typedef int (C::* expected3)(int) volatile;
+typedef int (C::* expected4)(int) const volatile;
+
+// implicitly specified cv qualification
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C,int> >::type
+ , expected1 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C const,int> >::type
+ , expected2 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer<
+ mpl::vector<int,C volatile,int> >::type
+ , expected3 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer<
+ mpl::vector<int,C const volatile,int> >::type
+ , expected4 >
+));
+
+// implicit & explicit/overrides
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer<
+ mpl::vector<int,C const volatile,int>
+ , ft::tag<ft::non_const, ft::non_volatile> >::type
+ , expected1 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C volatile,int>,
+ ft::tag<ft::const_qualified, ft::non_volatile> >::type
+ , expected2 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C const,int>,
+ ft::tag<ft::non_const, ft::volatile_qualified> >::type
+ , expected3 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C const,int>,
+ ft::tag<ft::const_qualified, ft::volatile_qualified> >::type
+ , expected4 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C volatile,int>,
+ ft::tag<ft::const_qualified, ft::volatile_qualified> >::type
+ , expected4 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C volatile,int>
+ , ft::const_qualified >::type
+ , expected4 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C const,int>
+ , ft::volatile_qualified >::type
+ , expected4 >
+));
+
+
diff --git a/src/boost/libs/function_types/test/synthesis/mem_func_ptr_cv2.cpp b/src/boost/libs/function_types/test/synthesis/mem_func_ptr_cv2.cpp
new file mode 100644
index 000000000..007efa038
--- /dev/null
+++ b/src/boost/libs/function_types/test/synthesis/mem_func_ptr_cv2.cpp
@@ -0,0 +1,94 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/function_types/member_function_pointer.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+using boost::is_same;
+
+class C;
+
+typedef int (C::* expected1)(int);
+typedef int (C::* expected2)(int) const;
+typedef int (C::* expected3)(int) volatile;
+typedef int (C::* expected4)(int) const volatile;
+
+// implicitly specified cv qualification
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C &,int> >::type
+ , expected1 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C const &,int> >::type
+ , expected2 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer<
+ mpl::vector<int,C volatile &,int> >::type
+ , expected3 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer<
+ mpl::vector<int,C const volatile &,int> >::type
+ , expected4 >
+));
+
+// implicit & explicit/overrides
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer<
+ mpl::vector<int,C const volatile &,int>
+ , ft::tag<ft::non_const, ft::non_volatile> >::type
+ , expected1 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C volatile &,int>,
+ ft::tag<ft::const_qualified, ft::non_volatile> >::type
+ , expected2 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C const &,int>,
+ ft::tag<ft::non_const, ft::volatile_qualified> >::type
+ , expected3 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C const &,int>,
+ ft::tag<ft::const_qualified, ft::volatile_qualified> >::type
+ , expected4 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C volatile &,int>,
+ ft::tag<ft::const_qualified, ft::volatile_qualified> >::type
+ , expected4 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C volatile &,int>
+ , ft::const_qualified >::type
+ , expected4 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C const &,int>
+ , ft::volatile_qualified >::type
+ , expected4 >
+));
+
+
diff --git a/src/boost/libs/function_types/test/synthesis/mem_func_ptr_cv_ptr_to_this.cpp b/src/boost/libs/function_types/test/synthesis/mem_func_ptr_cv_ptr_to_this.cpp
new file mode 100644
index 000000000..1b6d906fe
--- /dev/null
+++ b/src/boost/libs/function_types/test/synthesis/mem_func_ptr_cv_ptr_to_this.cpp
@@ -0,0 +1,37 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/function_types/member_function_pointer.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+using boost::is_same;
+
+class C;
+typedef int (C::* expected)();
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C * const> >::type
+ , expected >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C * volatile> >::type
+ , expected >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C * const volatile> >::type
+ , expected >
+));
+
+
+
diff --git a/src/boost/libs/function_types/test/synthesis/member_function_pointer.cpp b/src/boost/libs/function_types/test/synthesis/member_function_pointer.cpp
new file mode 100644
index 000000000..6234c474f
--- /dev/null
+++ b/src/boost/libs/function_types/test/synthesis/member_function_pointer.cpp
@@ -0,0 +1,66 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/function_types/member_function_pointer.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+using boost::is_same;
+
+class C;
+
+typedef int (C::* expected1)(int);
+typedef int (C::* expected2)(int) const;
+typedef int (C::* expected3)(int) volatile;
+typedef int (C::* expected4)(int) const volatile;
+
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C,int> >::type
+ , expected1 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C,int>,
+ ft::tag<ft::non_const, ft::non_volatile> >::type
+ , expected1 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C,int>
+ , ft::const_qualified >::type
+ , expected2 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C,int>,
+ ft::tag<ft::const_qualified, ft::non_volatile> >::type
+ , expected2 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C,int>
+ , ft::volatile_qualified >::type
+ , expected3 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C,int>,
+ ft::tag<ft::non_const, ft::volatile_qualified> >::type
+ , expected3 >
+));
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_function_pointer< mpl::vector<int,C,int>,
+ ft::tag<ft::const_qualified, ft::volatile_qualified> >::type
+ , expected4 >
+));
+
diff --git a/src/boost/libs/function_types/test/synthesis/member_object_pointer.cpp b/src/boost/libs/function_types/test/synthesis/member_object_pointer.cpp
new file mode 100644
index 000000000..65af74121
--- /dev/null
+++ b/src/boost/libs/function_types/test/synthesis/member_object_pointer.cpp
@@ -0,0 +1,27 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/function_types/member_object_pointer.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+using boost::is_same;
+
+class C;
+
+typedef int C::* expected;
+
+
+BOOST_MPL_ASSERT((
+ is_same< ft::member_object_pointer< mpl::vector<int,C> >::type
+ , expected >
+));
+
diff --git a/src/boost/libs/function_types/test/synthesis/transformation.cpp b/src/boost/libs/function_types/test/synthesis/transformation.cpp
new file mode 100644
index 000000000..38856476a
--- /dev/null
+++ b/src/boost/libs/function_types/test/synthesis/transformation.cpp
@@ -0,0 +1,75 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/function_types/function_type.hpp>
+#include <boost/function_types/function_pointer.hpp>
+#include <boost/function_types/function_reference.hpp>
+#include <boost/function_types/member_function_pointer.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+using boost::is_same;
+
+class C;
+
+typedef C func1(C &);
+typedef C (*func_ptr1)(C &);
+typedef C (&func_ref1)(C &);
+typedef C (C::*mem_func_ptr1)();
+
+BOOST_MPL_ASSERT(( is_same< func1, ft::function_type<func1>::type > ));
+BOOST_MPL_ASSERT(( is_same< func1, ft::function_type<func_ptr1>::type > ));
+BOOST_MPL_ASSERT(( is_same< func1, ft::function_type<func_ref1>::type > ));
+BOOST_MPL_ASSERT(( is_same< func1, ft::function_type<mem_func_ptr1>::type > ));
+
+BOOST_MPL_ASSERT(( is_same< func_ptr1, ft::function_pointer<func1>::type > ));
+BOOST_MPL_ASSERT(( is_same< func_ptr1, ft::function_pointer<func_ptr1>::type > ));
+BOOST_MPL_ASSERT(( is_same< func_ptr1, ft::function_pointer<func_ref1>::type > ));
+BOOST_MPL_ASSERT(( is_same< func_ptr1, ft::function_pointer<mem_func_ptr1>::type > ));
+
+BOOST_MPL_ASSERT(( is_same< func_ref1, ft::function_reference<func1>::type > ));
+BOOST_MPL_ASSERT(( is_same< func_ref1, ft::function_reference<func_ptr1>::type > ));
+BOOST_MPL_ASSERT(( is_same< func_ref1, ft::function_reference<func_ref1>::type > ));
+BOOST_MPL_ASSERT(( is_same< func_ref1, ft::function_reference<mem_func_ptr1>::type > ));
+
+BOOST_MPL_ASSERT(( is_same< mem_func_ptr1, ft::member_function_pointer<func1>::type > ));
+BOOST_MPL_ASSERT(( is_same< mem_func_ptr1, ft::member_function_pointer<func_ptr1>::type > ));
+BOOST_MPL_ASSERT(( is_same< mem_func_ptr1, ft::member_function_pointer<func_ref1>::type > ));
+BOOST_MPL_ASSERT(( is_same< mem_func_ptr1, ft::member_function_pointer<mem_func_ptr1>::type > ));
+
+
+typedef C func2(C const &);
+typedef C (*func_ptr2)(C const &);
+typedef C (&func_ref2)(C const &);
+typedef C (C::*mem_func_ptr2)() const;
+
+BOOST_MPL_ASSERT(( is_same< func2, ft::function_type<func2>::type > ));
+BOOST_MPL_ASSERT(( is_same< func2, ft::function_type<func_ptr2>::type > ));
+BOOST_MPL_ASSERT(( is_same< func2, ft::function_type<func_ref2>::type > ));
+BOOST_MPL_ASSERT(( is_same< func2, ft::function_type<mem_func_ptr2>::type > ));
+
+BOOST_MPL_ASSERT(( is_same< func_ptr2, ft::function_pointer<func2>::type > ));
+BOOST_MPL_ASSERT(( is_same< func_ptr2, ft::function_pointer<func_ptr2>::type > ));
+BOOST_MPL_ASSERT(( is_same< func_ptr2, ft::function_pointer<func_ref2>::type > ));
+BOOST_MPL_ASSERT(( is_same< func_ptr2, ft::function_pointer<mem_func_ptr2>::type > ));
+
+BOOST_MPL_ASSERT(( is_same< func_ref2, ft::function_reference<func2>::type > ));
+BOOST_MPL_ASSERT(( is_same< func_ref2, ft::function_reference<func_ptr2>::type > ));
+BOOST_MPL_ASSERT(( is_same< func_ref2, ft::function_reference<func_ref2>::type > ));
+BOOST_MPL_ASSERT(( is_same< func_ref2, ft::function_reference<mem_func_ptr2>::type > ));
+
+BOOST_MPL_ASSERT(( is_same< mem_func_ptr2, ft::member_function_pointer<func2>::type > ));
+BOOST_MPL_ASSERT(( is_same< mem_func_ptr2, ft::member_function_pointer<func_ptr2>::type > ));
+BOOST_MPL_ASSERT(( is_same< mem_func_ptr2, ft::member_function_pointer<func_ref2>::type > ));
+BOOST_MPL_ASSERT(( is_same< mem_func_ptr2, ft::member_function_pointer<mem_func_ptr2>::type > ));
+
+
+
diff --git a/src/boost/libs/function_types/test/synthesis/variadic_function_synthesis.cpp b/src/boost/libs/function_types/test/synthesis/variadic_function_synthesis.cpp
new file mode 100644
index 000000000..d35b31911
--- /dev/null
+++ b/src/boost/libs/function_types/test/synthesis/variadic_function_synthesis.cpp
@@ -0,0 +1,63 @@
+
+// (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).
+
+//------------------------------------------------------------------------------
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/function_types/function_type.hpp>
+#include <boost/function_types/function_pointer.hpp>
+#include <boost/function_types/function_reference.hpp>
+#include <boost/function_types/member_function_pointer.hpp>
+
+namespace ft = boost::function_types;
+namespace mpl = boost::mpl;
+using boost::is_same;
+
+class C;
+typedef int expected_v_1(...);
+typedef int expected_nv_1();
+typedef int (C::*expected_v_2)(...);
+typedef int (C::*expected_nv_2)();
+
+BOOST_MPL_ASSERT(( is_same<
+ ft::function_type<mpl::vector<int>, ft::variadic>::type, expected_v_1
+> ));
+
+BOOST_MPL_ASSERT(( is_same<
+ ft::function_type<mpl::vector<int>, ft::non_variadic>::type, expected_nv_1
+> ));
+
+BOOST_MPL_ASSERT(( is_same<
+ ft::function_pointer<mpl::vector<int>, ft::variadic>::type, expected_v_1 *
+> ));
+
+BOOST_MPL_ASSERT(( is_same<
+ ft::function_pointer<mpl::vector<int>, ft::non_variadic>::type
+ , expected_nv_1 *
+> ));
+
+BOOST_MPL_ASSERT(( is_same<
+ ft::function_reference<mpl::vector<int>, ft::variadic>::type, expected_v_1 &
+> ));
+
+BOOST_MPL_ASSERT(( is_same<
+ ft::function_reference<mpl::vector<int>, ft::non_variadic>::type
+ , expected_nv_1 &
+> ));
+
+BOOST_MPL_ASSERT(( is_same<
+ ft::member_function_pointer<mpl::vector<int,C>, ft::variadic>::type
+ , expected_v_2
+> ));
+
+BOOST_MPL_ASSERT(( is_same<
+ ft::member_function_pointer<mpl::vector<int,C>, ft::non_variadic>::type
+ , expected_nv_2
+> ));
+