fork download
  1. #include <cstdint>
  2. #include <type_traits>
  3.  
  4. #define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature) \
  5.   template <typename U> \
  6.   class traitsName \
  7.   { \
  8.   private: \
  9.   template<typename T, T> struct helper; \
  10.   template<typename T> \
  11.   static std::uint8_t check(helper<signature, &funcName>*); \
  12.   template<typename T> static std::uint16_t check(...); \
  13.   public: \
  14.   static \
  15.   constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); \
  16.   }
  17.  
  18. DEFINE_HAS_SIGNATURE(has_ref_swap, T::swap, void (T::*)(T&));
  19. DEFINE_HAS_SIGNATURE(has_value_swap, T::swap, void (T::*)(T));
  20.  
  21. template <typename T>
  22. struct MetaHelperType_impl
  23. {
  24. static_assert(!has_value_swap<T>::value,
  25. "Incorrect implementation of T::swap, "
  26. "signature should be void T::swap(T&) instead of T::swap(T)");
  27.  
  28. using type = std::conditional_t<has_ref_swap<T>::value,
  29. std::true_type,
  30. std::false_type>;
  31. };
  32.  
  33. template <typename T>
  34. using MetaHelperType = typename MetaHelperType_impl<T>::type;
  35.  
  36. struct NonReferenceSwap
  37. {
  38. void swap(NonReferenceSwap) {}
  39. };
  40.  
  41. struct ReferenceSwap
  42. {
  43. void swap(ReferenceSwap &) {}
  44. };
  45.  
  46. struct NoSwapFunction {};
  47.  
  48. int main() {
  49. static_assert(MetaHelperType<ReferenceSwap>::value, "unexpected result");
  50. static_assert(!MetaHelperType<NoSwapFunction>::value, "unexpected result");
  51. static_assert(!MetaHelperType<NonReferenceSwap>::value, "unexpected result"); // Doesn't compile as expected
  52. }
Compilation error #stdin compilation error #stdout 0s 3408KB
stdin
Standard input is empty
compilation info
prog.cpp: In instantiation of 'struct MetaHelperType_impl<NonReferenceSwap>':
prog.cpp:34:61:   required by substitution of 'template<class T> using MetaHelperType = typename MetaHelperType_impl::type [with T = NonReferenceSwap]'
prog.cpp:51:48:   required from here
prog.cpp:24:5: error: static assertion failed: Incorrect implementation of T::swap, signature should be void T::swap(T&) instead of T::swap(T)
     static_assert(!has_value_swap<T>::value,
     ^
stdout
Standard output is empty