blob: 381ee146e54bd3e589e9980c516e52337572321f [file] [log] [blame]
Brian Silverman57be3162018-08-04 23:36:33 -07001
2// (C) Copyright Tobias Schwinger
3//
4// Use modification and distribution are subject to the boost Software License,
5// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt).
6
7//------------------------------------------------------------------------------
8// See fast_mem_fn.hpp in this directory for details.
9
10#include <vector>
11#include <cassert>
12#include <iostream>
13#include <algorithm>
14#include <functional>
15
16#include <boost/timer.hpp>
17#include <boost/mem_fn.hpp>
18
19#include "fast_mem_fn.hpp"
20
21// test class that holds a single integer with getter function
22class test
23{
24 int val_id;
25public:
26
27 explicit test(int id)
28 : val_id(id)
29 { }
30
31 int id() const
32 { return val_id; }
33
34};
35
36// STL style comparator that applies the CriterionExtractor function to both
37// operands and compares the results with Comparator
38template<typename CriterionExtractor, typename Comparator>
39class test_compare
40{
41 CriterionExtractor fnc_criterion;
42 Comparator fnc_compare;
43public:
44
45 explicit test_compare(CriterionExtractor criterion, Comparator compare)
46 : fnc_criterion(criterion)
47 , fnc_compare(compare)
48 { }
49
50 template<typename T>
51 inline bool operator()(T const & lhs, T const & rhs) const
52 {
53 return fnc_compare(fnc_criterion(lhs),fnc_criterion(rhs));
54 }
55};
56
57// helper function to construct an instance of the test_compare comparator.
58template<typename CriterionExtractor, typename Comparator>
59test_compare<CriterionExtractor,Comparator>
60make_test_compare(CriterionExtractor criterion, Comparator compare)
61{
62 return test_compare<CriterionExtractor,Comparator>(criterion,compare);
63}
64
65// the test case: sort N test objects by id
66//
67// the objects are in ascending order before the test run and in descending
68// order after it
69
70static const unsigned N = 2000000;
71
72typedef std::vector<test> test_vector;
73
74
75void setup_test(test_vector & v)
76{
77 v.clear();
78 v.reserve(N);
79 for (unsigned i = 0; i < N; ++i)
80 v.push_back(test(i));
81}
82
83template<typename F> void do_test(test_vector & v, F criterion)
84{
85 std::sort(v.begin(),v.end(),make_test_compare(criterion,std::greater<int>()));
86 assert(v.begin()->id() == N-1);
87}
88
89
90// compare performance with boost::mem_fn
91int main()
92{
93 test_vector v;
94 boost::timer t;
95 double time1, time2;
96
97 std::cout <<
98 "Test case: sorting " << N << " objects.\n\n"
99 "Criterion accessor called with | elasped seconds\n"
100 "-------------------------------|----------------" << std::endl;
101
102 setup_test(v);
103 t.restart();
104#if !BOOST_WORKAROUND(BOOST_MSVC, < 1400)
105 do_test(v, BOOST_EXAMPLE_FAST_MEM_FN(& test::id));
106#else // MSVC<8 does not like the implementation of the deduction macro:
107 do_test(v, ::example::fast_mem_fn< int (test::*)() const, & test::id >());
108#endif
109 time1 = t.elapsed();
110 std::cout << "fast_mem_fn | " << time1 << std::endl;
111
112 setup_test(v);
113 t.restart();
114 do_test(v, boost::mem_fn(& test::id));
115 time2 = t.elapsed();
116 std::cout << "mem_fn | " << time2 << std::endl;
117
118 std::cout << '\n' << (time2/time1-1)*100 << "% speedup" << std::endl;
119
120 return 0;
121}
122