fork download
  1. #include <iostream>
  2. #include <unistd.h>
  3. #include <sys/times.h>
  4.  
  5. #define SUBCLASSES \
  6.   SUBCLASS(A) SUBCLASS(B) SUBCLASS(C) SUBCLASS(D) SUBCLASS(E) \
  7.   SUBCLASS(F) SUBCLASS(G)
  8.  
  9. #define SUBCLASS(X) struct X ;
  10. SUBCLASSES
  11. #undef SUBCLASS
  12.  
  13. struct Base;
  14.  
  15. // Use this as a way to hack template specialization of template method
  16. template <typename MAYBE_DERIVED>
  17. struct BaseIsTypeOrSubtype {
  18. MAYBE_DERIVED * operator () (Base *) const { return 0; }
  19. };
  20.  
  21. struct Base {
  22. Base () { std::cout << __func__ << std::endl; }
  23. virtual ~Base () {}
  24.  
  25. template <typename MAYBE_DERIVED> MAYBE_DERIVED * isTypeOrSubtype () {
  26. return BaseIsTypeOrSubtype<MAYBE_DERIVED>()(this);
  27. }
  28.  
  29. #define SUBCLASS(X) virtual X * is_##X () { return 0; }
  30. SUBCLASSES
  31. #undef SUBCLASS
  32. };
  33.  
  34. #define SUBCLASS(X) \
  35.   template <> struct BaseIsTypeOrSubtype<X> { \
  36.   X * operator () (Base *b) const { return b->is_##X(); } \
  37.   };
  38. SUBCLASSES
  39. #undef SUBCLASS
  40.  
  41. #define FOO(X) \
  42.   X () : count_(0) {} \
  43.   X * is_##X () { return this; } \
  44.   void foo () { if (this) { count_ += 1; } } \
  45.   int count () { return this ? count_ : 0; } \
  46.   private: int count_
  47.  
  48. struct A : virtual Base { FOO(A); };
  49. struct B : A { FOO(B); };
  50. struct C : A { FOO(C); };
  51. struct D : virtual Base { FOO(D); };
  52. struct E : D { FOO(E); };
  53. struct F : D { FOO(F); };
  54. struct G : B, F { FOO(G); };
  55.  
  56. void foo (Base *b) {
  57. for (int i = 0; i < 20000000; ++i) {
  58. b->isTypeOrSubtype<E>()->foo();
  59. }
  60. }
  61.  
  62. void foo_dc (Base *b) {
  63. for (int i = 0; i < 2000000; ++i) {
  64. dynamic_cast<E *>(b)->foo();
  65. }
  66. }
  67.  
  68. void bar (Base *b) {
  69. for (int i = 0; i < 20000000; ++i) {
  70. b->isTypeOrSubtype<C>()->foo();
  71. }
  72. }
  73.  
  74. void bar_dc (Base *b) {
  75. for (int i = 0; i < 2000000; ++i) {
  76. dynamic_cast<C *>(b)->foo();
  77. }
  78. }
  79.  
  80. void report (struct tms &start, struct tms &finish, Base *x, int f = 1) {
  81. double ticks_per_sec = sysconf(_SC_CLK_TCK);
  82. unsigned long long elapsed = 0;
  83. elapsed += finish.tms_utime;
  84. elapsed += finish.tms_stime;
  85. elapsed -= start.tms_utime;
  86. elapsed -= start.tms_stime;
  87. int countC = x->isTypeOrSubtype<C>()->count();
  88. int countE = x->isTypeOrSubtype<E>()->count();
  89. std::cout << countC + countE << " hits, "
  90. << f * elapsed/ticks_per_sec << " seconds"
  91. << std::endl;
  92. }
  93.  
  94. void run_test (void (*test)(Base *), Base *x, int f = 1) {
  95. struct tms start;
  96. struct tms finish;
  97. times(&start);
  98. test(x);
  99. times(&finish);
  100. report(start, finish, x, f);
  101. }
  102.  
  103. int main () {
  104. G g;
  105. C c;
  106. E e;
  107.  
  108. run_test(foo, &g); //--> 0 g is not an E
  109. run_test(bar, &g); //--> 0 g is not a C
  110.  
  111. run_test(foo, &c); //--> 0 c is not an E
  112. run_test(bar, &c); //--> 20000000 c is a C
  113.  
  114. run_test(foo, &e); //--> 20000000 e is an E
  115. run_test(bar, &e); //--> 20000000 e is not a C
  116. }
  117.  
Success #stdin #stdout 0.45s 3348KB
stdin
Standard input is empty
stdout
Base
Base
Base
0 hits, 0.07 seconds
0 hits, 0.07 seconds
0 hits, 0.07 seconds
20000000 hits, 0.09 seconds
20000000 hits, 0.08 seconds
20000000 hits, 0.07 seconds