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....@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....@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. 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<></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<>() );