Date
2015-03-02.20:01:41
Message id
7159

Content

less<void>::operator(t, u) (and the same applies to the rest of void specializations for standard comparison function objects) returns t < u even if t and u are pointers, which by [expr.rel]/3 is undefined except if both pointers point to the same array or object. This might be regarded as a specification defect since the intention of N3421 is that less<> can substitute for less<T> in any case where the latter is applicable. less<void> can be rewritten in the following manner to cope with pointers:

template<> struct less<void>
{

  typedef unspecified is_transparent;

  template <class T, class U>
  struct pointer_overload : std::is_pointer<std::common_type_t<T, U>>
  {};

  template <
    class T, class U,
    typename std::enable_if<!pointer_overload<T, U>::value>::type* = nullptr
  >
  auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) < std::forward<U>(u))
  {
    return std::forward<T>(t) < std::forward<U>(u);
  } 

  template <
    class T, class U,
    typename std::enable_if<pointer_overload<T, U>::value>::type* = nullptr
  >
  auto operator()(T&& t, U&& u) const
    -> decltype(std::declval<std::less<std::common_type_t<T, U>>>()(std::forward<T>(t), std::forward<U>(u)))
  {
    std::less<std::common_type_t<T, U>> l;
    return l(std::forward<T>(t), std::forward<U>(u));
  }

};

This wording is relative to N4140.

  1. Change [comparisons] p14 as indicated:

    -14- For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not. For template specializations greater<void>, less<void>, greater_equal<void>, and less_equal<void>, the call operator with arguments whose common type CT is a pointer yields the same value as the corresponding comparison function object class specialization for CT.