fork download
  1. #include <iostream>
  2. #include <vector>
  3.  
  4. template <typename> struct Tag {};
  5.  
  6. template <typename T>
  7. class TemplateClass
  8. {
  9. public:
  10. auto print() -> decltype(helper_print(Tag<T>{})) // SFINAE friendly
  11. // void print() // Simple, but SFINAE unfriendly
  12. { return helper_print(Tag<T>{}); }
  13. };
  14.  
  15.  
  16. void helper_print(Tag<int>)
  17. {
  18. std::cout << "T is an int!" << std::endl;
  19. }
  20. void helper_print(Tag<float>)
  21. {
  22. std::cout << "T is a float!" << std::endl;
  23. }
  24.  
  25. template <typename U>
  26. void helper_print(Tag<std::vector<U>>)
  27. {
  28. std::cout << "T is a std::vector!" << std::endl;
  29. }
  30.  
  31.  
  32. template <typename T> class BaseOne {};
  33. template <typename T> class BaseTwo {};
  34.  
  35. struct DerivedOne : public BaseOne<DerivedOne>
  36. {
  37. int i;
  38. };
  39.  
  40. struct DerivedTwo : public BaseTwo<DerivedTwo>
  41. {
  42. float x, y, z;
  43. };
  44.  
  45. // Create traits
  46. template <template <typename> class C, typename U>
  47. std::true_type HasTemplateBaseImpl(C<U>*);
  48.  
  49. template <template <typename> class C>
  50. std::false_type HasTemplateBaseImpl(...);
  51.  
  52. template <typename T, template <typename> class C>
  53. using has_template_base = decltype(HasTemplateBaseImpl<C>(std::declval<T*>()));
  54.  
  55. static_assert(has_template_base<DerivedOne, BaseOne>::value, "!");
  56. static_assert(has_template_base<DerivedTwo, BaseTwo>::value, "!");
  57.  
  58. template <typename T,
  59. std::enable_if_t<has_template_base<T, BaseOne>::value, bool> = false>
  60. void helper_print(Tag<T>)
  61. {
  62. std::cout << "T is derived from BaseOne!" << std::endl;
  63. }
  64.  
  65. template <typename T,
  66. std::enable_if_t<has_template_base<T, BaseTwo>::value, bool> = false>
  67. void helper_print(Tag<T>)
  68. {
  69. std::cout << "T is derived from BaseTwo!" << std::endl;
  70. }
  71.  
  72. int main()
  73. {
  74. TemplateClass<int> i;
  75. i.print();
  76.  
  77. TemplateClass<float> f;
  78. f.print();
  79.  
  80.  
  81. TemplateClass<std::vector<int>> v;
  82. v.print();
  83.  
  84. TemplateClass<DerivedOne> d1;
  85. d1.print();
  86.  
  87. TemplateClass<DerivedTwo> d2;
  88. d2.print();
  89. }
  90.  
Success #stdin #stdout 0s 15232KB
stdin
Standard input is empty
stdout
T is an int!
T is a float!
T is a std::vector!
T is derived from BaseOne!
T is derived from BaseTwo!