fork download
  1. #include <iostream>
  2. #include <unordered_map>
  3. #include <map>
  4. #include <iostream>
  5. #include <typeinfo>
  6. #include <unistd.h>
  7. #include <sys/times.h>
  8.  
  9. struct Base {
  10. typedef std::map<const char *, void *> MapType;
  11. MapType children_;
  12.  
  13. Base () { std::cout << __func__ << std::endl; }
  14. virtual ~Base () {}
  15.  
  16. template <typename MAYBE_DERIVED>
  17. MAYBE_DERIVED * isTypeOrSubtype () {
  18. auto x = children_.find(typeid(MAYBE_DERIVED).name());
  19. return ((x != children_.end())
  20. ? static_cast<MAYBE_DERIVED *>(x->second)
  21. : 0);
  22. }
  23. };
  24.  
  25. #define FOO(X) \
  26.   X () : count_(0) { children_[typeid(X).name()] = this; } \
  27.   void foo () { if (this) { count_ += 1; } } \
  28.   int count () { return this ? count_ : 0; } \
  29.   private: int count_
  30.  
  31. struct A : virtual Base { FOO(A); };
  32. struct B : A { FOO(B); };
  33. struct C : A { FOO(C); };
  34. struct D : virtual Base { FOO(D); };
  35. struct E : D { FOO(E); };
  36. struct F : D { FOO(F); };
  37. struct G : B, F { FOO(G); };
  38.  
  39. void foo (Base *b) {
  40. for (int i = 0; i < 20000000; ++i) {
  41. b->isTypeOrSubtype<E>()->foo();
  42. }
  43. }
  44.  
  45. void foo_dc (Base *b) {
  46. for (int i = 0; i < 2000000; ++i) {
  47. dynamic_cast<E *>(b)->foo();
  48. }
  49. }
  50.  
  51. void bar (Base *b) {
  52. for (int i = 0; i < 20000000; ++i) {
  53. b->isTypeOrSubtype<C>()->foo();
  54. }
  55. }
  56.  
  57. void bar_dc (Base *b) {
  58. for (int i = 0; i < 2000000; ++i) {
  59. dynamic_cast<C *>(b)->foo();
  60. }
  61. }
  62.  
  63. void report (struct tms &start, struct tms &finish, Base *x, int f = 1) {
  64. double ticks_per_sec = sysconf(_SC_CLK_TCK);
  65. unsigned long long elapsed = 0;
  66. elapsed += finish.tms_utime;
  67. elapsed += finish.tms_stime;
  68. elapsed -= start.tms_utime;
  69. elapsed -= start.tms_stime;
  70. int countC = x->isTypeOrSubtype<C>()->count();
  71. int countE = x->isTypeOrSubtype<E>()->count();
  72. std::cout << countC + countE << " hits, "
  73. << f * elapsed/ticks_per_sec << " seconds"
  74. << std::endl;
  75. }
  76.  
  77. void run_test (void (*test)(Base *), Base *x, int f = 1) {
  78. struct tms start;
  79. struct tms finish;
  80. times(&start);
  81. test(x);
  82. times(&finish);
  83. report(start, finish, x, f);
  84. }
  85.  
  86. int main () {
  87. G g;
  88. C c;
  89. E e;
  90.  
  91. run_test(foo_dc, &g, 10); //--> 0 g is not an E
  92. run_test(bar_dc, &g, 10); //--> 0 g is not a C
  93.  
  94. run_test(foo_dc, &c, 10); //--> 0 c is not an E
  95. run_test(bar_dc, &c, 10); //--> 2000000 c is a C
  96.  
  97. run_test(foo_dc, &e, 10); //--> 2000000 e is an E
  98. run_test(bar_dc, &e, 10); //--> 2000000 e is not a C
  99. }
Success #stdin #stdout 1.47s 3436KB
stdin
Standard input is empty
stdout
Base
Base
Base
0 hits, 4.5 seconds
0 hits, 4.4 seconds
0 hits, 1.7 seconds
2000000 hits, 1.2 seconds
2000000 hits, 1.2 seconds
2000000 hits, 1.7 seconds