fork download
  1. #include <utility>
  2. #include <iostream>
  3.  
  4. template<class...>struct types{using type=types;};
  5.  
  6. template<typename T>
  7. struct fast_castable_leaf {
  8. virtual T* do_fast_cast(T* unused=nullptr) { return nullptr; }
  9. virtual T const* do_fast_cast(T* unused=nullptr) const { return nullptr; }
  10. virtual ~fast_castable_leaf() {}
  11. };
  12. template<class Tuple>
  13. struct fast_castable;
  14. template<>
  15. struct fast_castable<types<>> {
  16. virtual ~fast_castable() {}
  17. };
  18. template<class T0, class...Ts>
  19. struct fast_castable<types<T0, Ts...>>:
  20. fast_castable_leaf<T0>,
  21. fast_castable<types<Ts...>>
  22. {};
  23. template<class T> struct block_deduction { typedef T type; };
  24. template<class T> using NoDeduction = typename block_deduction<T>::type;
  25. template<class T>
  26. T* fast_cast( NoDeduction<fast_castable_leaf<T>>* src ) {
  27. return src->do_fast_cast();
  28. }
  29. template<class T>
  30. T const* fast_cast( NoDeduction<fast_castable_leaf<T>> const* src ) {
  31. return src->do_fast_cast();
  32. }
  33.  
  34. template<class T, class D>
  35. struct fast_cast_allowed : std::integral_constant<bool,
  36. std::is_base_of<T,D>::value || std::is_same<T,D>::value
  37. > {};
  38.  
  39. template<class Self, class Base, class Types>
  40. struct implement_fast_cast;
  41.  
  42. template<class Self, class Base>
  43. struct implement_fast_cast<Self,Base,types<>> : Base {
  44. private:
  45. template<class, class, class>
  46. friend struct implement_fast_cast;
  47.  
  48. Self* do_cast_work(std::true_type) { return static_cast<Self*>(this); }
  49. Self const* do_cast_work(std::true_type) const { return static_cast<Self const*>(this); }
  50. std::nullptr_t do_cast_work(std::false_type) { return nullptr; }
  51. std::nullptr_t do_cast_work(std::false_type) const { return nullptr; }
  52. };
  53.  
  54. template<class Self, class Base, class T0, class... Ts>
  55. struct implement_fast_cast<Self,Base,types<T0,Ts...>> :
  56. implement_fast_cast<Self, Base, types<Ts...>>
  57. {
  58. public:
  59. T0* do_fast_cast( T0* unused = nullptr ) override { return this->do_cast_work( fast_cast_allowed<T0,Self>() ); }
  60. T0 const* do_fast_cast( T0* unused = nullptr ) const override { return this->do_cast_work( fast_cast_allowed<T0,Self>() ); }
  61. };
  62.  
  63. struct Dog;
  64. struct Cat;
  65. struct Moose;
  66. typedef types<Dog, Cat, Moose> Mammal_Types;
  67.  
  68. struct Mammal : fast_castable<Mammal_Types>
  69. {};
  70.  
  71. struct Cat : implement_fast_cast< Cat, Mammal, Mammal_Types >
  72. {};
  73.  
  74. int main() {
  75. Cat c;
  76. Mammal* m=&c;
  77. Cat* c2 = fast_cast<Cat>(m);
  78. Dog* d2 = fast_cast<Dog>(m);
  79. std::cout << c2 << "," << d2 << "\n";
  80. }
  81.  
Success #stdin #stdout 0s 3460KB
stdin
Standard input is empty
stdout
0xbf8609d0,0