Advertisement
Radfler

::mem_compare

Mar 7th, 2018
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 1.65 KB | None | 0 0
  1. #include <functional>
  2. #include <type_traits>
  3. #include <utility>
  4.  
  5. namespace details {
  6.  
  7.     template<typename Member, typename Class>
  8.     using member_result_t = std::decay_t<std::invoke_result_t<Member Class::*, Class>>;
  9.  
  10.     template<typename Member, typename Class, typename Compare>
  11.     class member_compare_t {
  12.  
  13.     private:
  14.  
  15.         using member_result_type = member_result_t<Member, Class>;
  16.  
  17.         static_assert(
  18.             std::is_invocable_r_v<bool, Compare, member_result_type, member_result_type>,
  19.             "Compare is not Predicate"
  20.         );
  21.  
  22.         static constexpr bool is_nothrow_comparable = noexcept(
  23.             std::declval<Compare>()(std::declval<member_result_type>(), std::declval<member_result_type>())
  24.         );
  25.  
  26.         static constexpr bool is_nothrow_constructible = noexcept(
  27.             std::is_nothrow_copy_constructible_v<Compare>
  28.         );
  29.  
  30.         Member Class::* pointer;
  31.         Compare compare;
  32.  
  33.     public:
  34.  
  35.         constexpr explicit
  36.             member_compare_t(Member Class::* pointer, const Compare& compare) noexcept(is_nothrow_constructible)
  37.             : pointer(pointer), compare(compare) {}
  38.  
  39.         constexpr bool operator()(const Class& left, const Class& right) const noexcept(is_nothrow_comparable) {
  40.  
  41.             if constexpr(std::is_member_object_pointer_v<Member Class::*>) {
  42.  
  43.                 return compare(left.*pointer, right.*pointer);
  44.  
  45.             } else {
  46.  
  47.                 return compare((left.*pointer)(), (right.*pointer)());
  48.  
  49.             }
  50.  
  51.         }
  52.  
  53.     };
  54.  
  55. }
  56.  
  57. template<typename Member, typename Class, typename Compare = std::less<details::member_result_t<Member, Class>>>
  58. constexpr decltype(auto) mem_compare(Member Class::* pointer, const Compare& compare = Compare()) {
  59.     return details::member_compare_t<Member, Class, Compare>(pointer, compare);
  60. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement