Patchwork [v3] Implement N3421 - make functors greater<>

login
register
mail settings
Submitter Jonathan Wakely
Date Nov. 1, 2013, 11:12 a.m.
Message ID <CAH6eHdQtKnQozgxffB53z+EPx29Qtwk_p2h0cOrBCzdhniTM4w@mail.gmail.com>
Download mbox | patch
Permalink /patch/287790/
State New
Headers show

Comments

Jonathan Wakely - Nov. 1, 2013, 11:12 a.m.
This implements another piece of the C++14 library, STL's "transparent
functors" proposal.  I also added the is_transparent typedefs, which
come from another proposal but modify these "diamond operators".  I
hope to get round to using those typedefs to implement Joaquin's
heterogeneous lookup soon.

2013-11-01  Jonathan Wakely  <jwakely.gcc@gmail.com>

        N3421 C++1y Transparent functors
        * include/bits/stl_function.h (plus<void>, minus<void>,
        multiplies<void>, divides<void>, modulus<void>, negate<void>,
        equal_to<void>, not_equal_to<void>, greater<void>, less<void>,
        greater_equal<void>, less_equal<void>, logical_and<void>,
        logical_or<void>, logical_not<void>, bit_and<void>, bit_or<void>,
        bit_xor<void>, bit_not<void>): Define.
        * doc/xml/manual/status_cxx2014.xml: Update.
        * testsuite/20_util/function_objects/comparisons_void.cc: New.

Tested x86_64-linux, committed to trunk.
commit 8382a58b1ba77be9f575caad84506362b2c87ad1
Author: Jonathan Wakely <jwakely.gcc@gmail.com>
Date:   Tue May 21 08:55:24 2013 +0100

    	N3421 C++1y Transparent functors
    	* include/bits/stl_function.h (plus<void>, minus<void>,
    	multiplies<void>, divides<void>, modulus<void>, negate<void>,
    	equal_to<void>, not_equal_to<void>, greater<void>, less<void>,
    	greater_equal<void>, less_equal<void>, logical_and<void>,
    	logical_or<void>, logical_not<void>, bit_and<void>, bit_or<void>,
    	bit_xor<void>, bit_not<void>): Define.
    	* doc/xml/manual/status_cxx2014.xml: Update.
    	* testsuite/20_util/function_objects/comparisons_void.cc: New.
    
    	* include/bits/stl_function.h: Implement N3421.
    	* testsuite/20_util/function_objects/comparisons_void.cc: New.
Marc Glisse - Nov. 1, 2013, 11:28 a.m.
On Fri, 1 Nov 2013, Jonathan Wakely wrote:

> 2013-11-01  Jonathan Wakely  <jwakely.gcc@gmail.com>
>
>        N3421 C++1y Transparent functors
>        * include/bits/stl_function.h (plus<void>, minus<void>,
>        multiplies<void>, divides<void>, modulus<void>, negate<void>,
>        equal_to<void>, not_equal_to<void>, greater<void>, less<void>,
>        greater_equal<void>, less_equal<void>, logical_and<void>,
>        logical_or<void>, logical_not<void>, bit_and<void>, bit_or<void>,
>        bit_xor<void>, bit_not<void>): Define.

Thanks. Why use noexcept for everything except logical_not?


I noticed recently that the following worked, it will be convenient now we 
have those functors (for my own code, not the STL):

template<typename RandomAccessIterator, typename Compare = std::less<void>>
void sort(RandomAccessIterator first, RandomAccessIterator last,
           Compare comp = {});
Jonathan Wakely - Nov. 1, 2013, 11:48 a.m.
On 1 November 2013 11:28, Marc Glisse wrote:
> On Fri, 1 Nov 2013, Jonathan Wakely wrote:
>
>> 2013-11-01  Jonathan Wakely  <jwakely.gcc@gmail.com>
>>
>>        N3421 C++1y Transparent functors
>>        * include/bits/stl_function.h (plus<void>, minus<void>,
>>        multiplies<void>, divides<void>, modulus<void>, negate<void>,
>>        equal_to<void>, not_equal_to<void>, greater<void>, less<void>,
>>        greater_equal<void>, less_equal<void>, logical_and<void>,
>>        logical_or<void>, logical_not<void>, bit_and<void>, bit_or<void>,
>>        bit_xor<void>, bit_not<void>): Define.
>
>
> Thanks. Why use noexcept for everything except logical_not?

Oops, because the regex I used to add noexcept only matched a
trailing-return-type on a line by itself, and I missed that one. I'll
fix it now, thanks!


> I noticed recently that the following worked, it will be convenient now we
> have those functors (for my own code, not the STL):
>
> template<typename RandomAccessIterator, typename Compare = std::less<void>>
> void sort(RandomAccessIterator first, RandomAccessIterator last,
>           Compare comp = {});

Nice :)

Patch

diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2014.xml b/libstdc++-v3/doc/xml/manual/status_cxx2014.xml
index 4ef4334..b368a81 100644
--- a/libstdc++-v3/doc/xml/manual/status_cxx2014.xml
+++ b/libstdc++-v3/doc/xml/manual/status_cxx2014.xml
@@ -209,7 +209,7 @@  particular release.
 	</link>
       </entry>
       <entry>Making Operator Functors greater&lt;&gt;</entry>
-      <entry>WIP</entry>
+      <entry>Y</entry>
       <entry/>
     </row>
 
diff --git a/libstdc++-v3/include/bits/stl_function.h b/libstdc++-v3/include/bits/stl_function.h
index 23529df..d2e5d13 100644
--- a/libstdc++-v3/include/bits/stl_function.h
+++ b/libstdc++-v3/include/bits/stl_function.h
@@ -56,6 +56,10 @@ 
 #ifndef _STL_FUNCTION_H
 #define _STL_FUNCTION_H 1
 
+#if __cplusplus > 201103L
+#include <bits/move.h>
+#endif
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -135,6 +139,29 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *
    *  @{
    */
+
+#if __cplusplus > 201103L
+  struct __is_transparent;  // undefined
+
+  template<typename _Tp = void>
+    struct plus;
+
+  template<typename _Tp = void>
+    struct minus;
+
+  template<typename _Tp = void>
+    struct multiplies;
+
+  template<typename _Tp = void>
+    struct divides;
+
+  template<typename _Tp = void>
+    struct modulus;
+
+  template<typename _Tp = void>
+    struct negate;
+#endif
+
   /// One of the @link arithmetic_functors math functors@endlink.
   template<typename _Tp>
     struct plus : public binary_function<_Tp, _Tp, _Tp>
@@ -188,6 +215,91 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       operator()(const _Tp& __x) const
       { return -__x; }
     };
+
+#if __cplusplus > 201103L
+  template<>
+    struct plus<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) + std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) + std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) + std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  /// One of the @link arithmetic_functors math functors@endlink.
+  template<>
+    struct minus<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) - std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) - std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) - std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  /// One of the @link arithmetic_functors math functors@endlink.
+  template<>
+    struct multiplies<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) * std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) * std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) * std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  /// One of the @link arithmetic_functors math functors@endlink.
+  template<>
+    struct divides<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) / std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) / std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) / std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  /// One of the @link arithmetic_functors math functors@endlink.
+  template<>
+    struct modulus<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) % std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) % std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) % std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  /// One of the @link arithmetic_functors math functors@endlink.
+  template<>
+    struct negate<void>
+    {
+      template <typename _Tp>
+	auto
+	operator()(_Tp&& __t) const
+	noexcept(noexcept(-std::forward<_Tp>(__t)))
+	-> decltype(-std::forward<_Tp>(__t))
+	{ return -std::forward<_Tp>(__t); }
+
+      typedef __is_transparent is_transparent;
+    };
+#endif
   /** @}  */
 
   // 20.3.3 comparisons
@@ -199,6 +311,26 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *
    *  @{
    */
+#if __cplusplus > 201103L
+  template<typename _Tp = void>
+    struct equal_to;
+
+  template<typename _Tp = void>
+    struct not_equal_to;
+
+  template<typename _Tp = void>
+    struct greater;
+
+  template<typename _Tp = void>
+    struct less;
+
+  template<typename _Tp = void>
+    struct greater_equal;
+
+  template<typename _Tp = void>
+    struct less_equal;
+#endif
+
   /// One of the @link comparison_functors comparison functors@endlink.
   template<typename _Tp>
     struct equal_to : public binary_function<_Tp, _Tp, bool>
@@ -252,6 +384,92 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       operator()(const _Tp& __x, const _Tp& __y) const
       { return __x <= __y; }
     };
+
+#if __cplusplus > 201103L
+  /// One of the @link comparison_functors comparison functors@endlink.
+  template<>
+    struct equal_to<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) == std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) == std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) == std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  /// One of the @link comparison_functors comparison functors@endlink.
+  template<>
+    struct not_equal_to<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) != std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) != std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) != std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  /// One of the @link comparison_functors comparison functors@endlink.
+  template<>
+    struct greater<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) > std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) > std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) > std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  /// One of the @link comparison_functors comparison functors@endlink.
+  template<>
+    struct less<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) < std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) < std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) < std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  /// One of the @link comparison_functors comparison functors@endlink.
+  template<>
+    struct greater_equal<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) >= std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) >= std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) >= std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  /// One of the @link comparison_functors comparison functors@endlink.
+  template<>
+    struct less_equal<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) <= std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) <= std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) <= std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+#endif
   /** @}  */
 
   // 20.3.4 logical operations
@@ -263,6 +481,17 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *
    *  @{
    */
+#if __cplusplus > 201103L
+  template<typename _Tp = void>
+    struct logical_and;
+
+  template<typename _Tp = void>
+    struct logical_or;
+
+  template<typename _Tp = void>
+    struct logical_not;
+#endif
+
   /// One of the @link logical_functors Boolean operations functors@endlink.
   template<typename _Tp>
     struct logical_and : public binary_function<_Tp, _Tp, bool>
@@ -289,8 +518,64 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       operator()(const _Tp& __x) const
       { return !__x; }
     };
+
+#if __cplusplus > 201103L
+  /// One of the @link logical_functors Boolean operations functors@endlink.
+  template<>
+    struct logical_and<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) && std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) && std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) && std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  /// One of the @link logical_functors Boolean operations functors@endlink.
+  template<>
+    struct logical_or<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) || std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) || std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) || std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  /// One of the @link logical_functors Boolean operations functors@endlink.
+  template<>
+    struct logical_not<void>
+    {
+      template <typename _Tp>
+	auto
+	operator()(_Tp&& __t) const -> decltype(!std::forward<_Tp>(__t))
+	{ return !std::forward<_Tp>(__t); }
+
+      typedef __is_transparent is_transparent;
+    };
+#endif
   /** @}  */
 
+#if __cplusplus > 201103L
+  template<typename _Tp = void>
+    struct bit_and;
+
+  template<typename _Tp = void>
+    struct bit_or;
+
+  template<typename _Tp = void>
+    struct bit_xor;
+
+  template<typename _Tp = void>
+    struct bit_not;
+#endif
+
   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   // DR 660. Missing Bitwise Operations.
   template<typename _Tp>
@@ -317,6 +602,68 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { return __x ^ __y; }
     };
 
+  template<typename _Tp>
+    struct bit_not : public unary_function<_Tp, _Tp>
+    {
+      _Tp
+      operator()(const _Tp& __x) const
+      { return ~__x; }
+    };
+
+#if __cplusplus > 201103L
+  template <>
+    struct bit_and<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) & std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) & std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) & std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  template <>
+    struct bit_or<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) | std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) | std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) | std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  template <>
+    struct bit_xor<void>
+    {
+      template <typename _Tp, typename _Up>
+	auto
+	operator()(_Tp&& __t, _Up&& __u) const
+	noexcept(noexcept(std::forward<_Tp>(__t) ^ std::forward<_Up>(__u)))
+	-> decltype(std::forward<_Tp>(__t) ^ std::forward<_Up>(__u))
+	{ return std::forward<_Tp>(__t) ^ std::forward<_Up>(__u); }
+
+      typedef __is_transparent is_transparent;
+    };
+
+  template <>
+    struct bit_not<void>
+    {
+      template <typename _Tp>
+	auto
+	operator()(_Tp&& __t) const
+	noexcept(noexcept(~std::forward<_Tp>(__t)))
+	-> decltype(~std::forward<_Tp>(__t))
+	{ return ~std::forward<_Tp>(__t); }
+
+      typedef __is_transparent is_transparent;
+    };
+#endif
+
   // 20.3.5 negators
   /** @defgroup negators Negators
    * @ingroup functors
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/comparisons_void.cc b/libstdc++-v3/testsuite/20_util/function_objects/comparisons_void.cc
new file mode 100644
index 0000000..2cea1fc
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/function_objects/comparisons_void.cc
@@ -0,0 +1,95 @@ 
+// { dg-options " -std=gnu++1y " }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 20.3.3 Comparisons
+
+#include <functional>
+
+struct R { };
+
+struct L
+{
+  L operator+(const R&) const { return *this; }
+  L operator-(const R&) const { return *this; }
+  L operator*(const R&) const { return *this; }
+  L operator/(const R&) const { return *this; }
+  L operator%(const R&) const { return *this; }
+  L operator-() const { return *this; }
+
+  bool operator==(const R&) const { return true; }
+  bool operator!=(const R&) const { return false; }
+  bool operator<(const R&) const { return false; }
+  bool operator<=(const R&) const { return true; }
+  bool operator>(const R&) const { return false; }
+  bool operator>=(const R&) const { return true; }
+
+  bool operator&&(const R&) const { return true; }
+  bool operator||(const R&) const { return true; }
+  bool operator!() const { return false; }
+
+  int operator&(const R&) const { return 1; }
+  int operator|(const R&) const { return 1; }
+  int operator^(const R&) const { return 0; }
+  int operator~() const { return 0; }
+};
+
+L l;
+R r;
+
+// test unary function objects
+template<typename F, typename Check = typename F::is_transparent>
+bool
+test1(F f)
+{
+  f(l);
+  return true;
+}
+
+// test binary function objects
+template<typename F, typename Check = typename F::is_transparent>
+bool
+test2(F f)
+{
+  f(l, r);
+  return true;
+}
+
+auto plus       = test2( std::plus<>() );
+auto minus      = test2( std::minus<>() );
+auto multiplies = test2( std::multiplies<>() );
+auto divides    = test2( std::divides<>() );
+auto modulus    = test2( std::modulus<>() );
+auto negate     = test1( std::negate<>() );
+
+auto equal_to       = test2( std::equal_to<>() );
+auto not_equal_to   = test2( std::not_equal_to<>() );
+auto greater        = test2( std::greater<>() );
+auto less           = test2( std::less<>() );
+auto greater_equal  = test2( std::greater_equal<>() );
+auto less_equal     = test2( std::less_equal<>() );
+
+auto logical_and    = test2( std::logical_and<>() );
+auto logical_or     = test2( std::logical_or<>() );
+auto logical_not    = test1( std::logical_not<>() );
+
+auto bit_and        = test2( std::bit_and<>() );
+auto bit_or         = test2( std::bit_or<>() );
+auto bit_xor        = test2( std::bit_xor<>() );
+auto bit_not        = test1( std::bit_not<>() );