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

Change-Id: I946aaade9862a3a50fdce89fbc618c914b0edae6
git-subtree-dir: third_party/boostorg/function_types
git-subtree-split: ae4fde2e2ae88291d6d656137169ff4003d184a1
diff --git a/example/fast_mem_fn_example.cpp b/example/fast_mem_fn_example.cpp
new file mode 100644
index 0000000..381ee14
--- /dev/null
+++ b/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;
+}
+