fast_mem_fn_example.cpp 3.0 KB

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