traits.hpp 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. //
  2. // traits.hpp
  3. // stream
  4. //
  5. // Created by Sam Jaffe on 6/24/17.
  6. //
  7. #pragma once
  8. #include <utility>
  9. namespace stream { namespace detail {
  10. template <typename T>
  11. struct ref_or_val {
  12. ref_or_val operator=(T && val) { value = std::move(val); return *this; }
  13. operator T const &() const { return value; }
  14. T value;
  15. };
  16. template <typename T>
  17. struct ref_or_val<T&> {
  18. ref_or_val operator=(T & val) { value = &val; return *this; }
  19. operator T &() const { return *value; }
  20. T * value;
  21. };
  22. template <typename F> struct map_member_object;
  23. template <typename T, typename R>
  24. struct map_member_object<R T::*> {
  25. using type = R const &;
  26. type operator()(T const & val) const { return val.*mem; }
  27. R T::*mem;
  28. };
  29. template <typename F> struct map_member_function;
  30. template <typename T, typename R>
  31. struct map_member_function<R (T::*)() const> {
  32. using type = R;
  33. type operator()(T const & val) const { return (val.*mem)(); }
  34. R (T::* mem)() const;
  35. };
  36. } }
  37. namespace stream { namespace traits {
  38. template <typename F>
  39. using memvar_f = typename detail::map_member_object<F>::type;
  40. template <typename F>
  41. using memfun_f = typename detail::map_member_function<F>::type;
  42. template <typename F>
  43. using is_memvar_t = typename std::enable_if<std::is_member_object_pointer<F>::value>::type;
  44. template <typename F>
  45. using is_memfun_t = typename std::enable_if<std::is_member_function_pointer<F>::value>::type;
  46. template <typename T, typename = void>
  47. struct is_dereferencable : public std::false_type {};
  48. template <>
  49. struct is_dereferencable<void*> : public std::false_type {};
  50. template <typename T>
  51. struct is_dereferencable<T, typename std::enable_if<!std::is_void<decltype(*std::declval<T>())>::value>::type> : public std::true_type {};
  52. template <typename T, typename F>
  53. using mapped_t = decltype(std::declval<F>()(std::declval<T>()));
  54. template <typename T, typename F>
  55. using fmapped_t = typename decltype(std::declval<F>()(std::declval<T>()))::value_type;
  56. } }