Home | History | Annotate | Download | only in test
      1 //===------------------------- dynamic_cast_stress.cpp --------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include <cassert>
     11 #include <tuple>
     12 #include <chrono>
     13 #include <iostream>
     14 
     15 template <std::size_t Indx, std::size_t Depth>
     16 struct C
     17     : public virtual C<Indx, Depth-1>,
     18       public virtual C<Indx+1, Depth-1>
     19 {
     20     virtual ~C() {}
     21 };
     22 
     23 template <std::size_t Indx>
     24 struct C<Indx, 0>
     25 {
     26     virtual ~C() {}
     27 };
     28 
     29 template <std::size_t Indx, std::size_t Depth>
     30 struct B
     31     : public virtual C<Indx, Depth-1>,
     32       public virtual C<Indx+1, Depth-1>
     33 {
     34 };
     35 
     36 template <class Indx, std::size_t Depth>
     37 struct makeB;
     38 
     39 template <std::size_t ...Indx, std::size_t Depth>
     40 struct makeB<std::__tuple_indices<Indx...>, Depth>
     41     : public B<Indx, Depth>...
     42 {
     43 };
     44 
     45 template <std::size_t Width, std::size_t Depth>
     46 struct A
     47     : public makeB<typename std::__make_tuple_indices<Width>::type, Depth>
     48 {
     49 };
     50 
     51 void test()
     52 {
     53     typedef std::chrono::high_resolution_clock Clock;
     54     typedef std::chrono::duration<double, std::micro> US;
     55     const std::size_t Width = 10;
     56     const std::size_t Depth = 5;
     57     A<Width, Depth> a;
     58     typedef B<Width/2, Depth> Destination;
     59 //    typedef A<Width, Depth> Destination;
     60     auto t0 = Clock::now();
     61     Destination* b = dynamic_cast<Destination*>((C<Width/2, 0>*)&a);
     62     auto t1 = Clock::now();
     63     std::cout << US(t1-t0).count() << " microseconds\n";
     64     assert(b != 0);
     65 }
     66 
     67 int main()
     68 {
     69     test();
     70 }
     71 
     72 /*
     73 Timing results I'm seeing (median of 3 microseconds):
     74 
     75                           libc++abi    gcc's dynamic_cast
     76 B<Width/2, Depth> -O3      48.334         93.190           libc++abi 93% faster
     77 B<Width/2, Depth> -Os      58.535         94.103           libc++abi 61% faster
     78 A<Width, Depth>   -O3      11.515         33.134           libc++abi 188% faster
     79 A<Width, Depth>   -Os      12.631         31.553           libc++abi 150% faster
     80 
     81 */
     82