diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2019-10-31 23:03:22 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2019-10-31 23:03:22 +0000 |
commit | 2670a7aa8f2680af6c113a6dec97f21d5715c809 (patch) | |
tree | 82f613b28f2cfdd2766fd23c15c8f31f99368c5a | |
parent | 328b52d6751733f6e0f2d31feca44e1d8f2abfc6 (diff) | |
download | gcc-2670a7aa8f2680af6c113a6dec97f21d5715c809.zip gcc-2670a7aa8f2680af6c113a6dec97f21d5715c809.tar.gz gcc-2670a7aa8f2680af6c113a6dec97f21d5715c809.tar.bz2 |
Add remaining changes from P1065R2 "constexpr INVOKE"
* include/bits/refwrap.h (reference_wrapper, ref, cref): Add constexpr
specifiers for C++20.
* include/std/functional (_Mem_fn, mem_fn, _Bind, _Bind_result, bind)
(bind_front, _Not_fn, not_fn): Likewise.
* testsuite/20_util/bind/constexpr.cc: New test.
* testsuite/20_util/function_objects/bind_front/constexpr.cc: New test.
* testsuite/20_util/function_objects/mem_fn/constexpr.cc: New test.
* testsuite/20_util/function_objects/not_fn/constexpr.cc: New test.
* testsuite/20_util/reference_wrapper/constexpr.cc: New test.
From-SVN: r277698
-rw-r--r-- | libstdc++-v3/ChangeLog | 10 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/refwrap.h | 10 | ||||
-rw-r--r-- | libstdc++-v3/include/std/functional | 49 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/bind/constexpr.cc | 43 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/function_objects/bind_front/constexpr.cc | 35 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/function_objects/mem_fn/constexpr.cc | 45 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/function_objects/not_fn/constexpr.cc | 35 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/reference_wrapper/constexpr.cc | 45 |
8 files changed, 257 insertions, 15 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 1004d76..0290111 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,15 @@ 2019-10-31 Jonathan Wakely <jwakely@redhat.com> + * include/bits/refwrap.h (reference_wrapper, ref, cref): Add constexpr + specifiers for C++20. + * include/std/functional (_Mem_fn, mem_fn, _Bind, _Bind_result, bind) + (bind_front, _Not_fn, not_fn): Likewise. + * testsuite/20_util/bind/constexpr.cc: New test. + * testsuite/20_util/function_objects/bind_front/constexpr.cc: New test. + * testsuite/20_util/function_objects/mem_fn/constexpr.cc: New test. + * testsuite/20_util/function_objects/not_fn/constexpr.cc: New test. + * testsuite/20_util/reference_wrapper/constexpr.cc: New test. + * doc/doxygen/user.cfg.in: Add new header. * include/Makefile.am: Add new header. * include/Makefile.in: Regenerate. diff --git a/libstdc++-v3/include/bits/refwrap.h b/libstdc++-v3/include/bits/refwrap.h index e810988..41e4653 100644 --- a/libstdc++-v3/include/bits/refwrap.h +++ b/libstdc++-v3/include/bits/refwrap.h @@ -300,7 +300,9 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) { _Tp* _M_data; + _GLIBCXX20_CONSTEXPR static _Tp* _S_fun(_Tp& __r) noexcept { return std::__addressof(__r); } + static void _S_fun(_Tp&&) = delete; template<typename _Up, typename _Up2 = __remove_cvref_t<_Up>> @@ -315,6 +317,7 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) // 3041. Unnecessary decay in reference_wrapper template<typename _Up, typename = __not_same<_Up>, typename = decltype(reference_wrapper::_S_fun(std::declval<_Up>()))> + _GLIBCXX20_CONSTEXPR reference_wrapper(_Up&& __uref) noexcept(noexcept(reference_wrapper::_S_fun(std::declval<_Up>()))) : _M_data(reference_wrapper::_S_fun(std::forward<_Up>(__uref))) @@ -325,14 +328,17 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) reference_wrapper& operator=(const reference_wrapper&) = default; + _GLIBCXX20_CONSTEXPR operator _Tp&() const noexcept { return this->get(); } + _GLIBCXX20_CONSTEXPR _Tp& get() const noexcept { return *_M_data; } template<typename... _Args> + _GLIBCXX20_CONSTEXPR typename result_of<_Tp&(_Args&&...)>::type operator()(_Args&&... __args) const { @@ -352,12 +358,14 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) /// Denotes a reference should be taken to a variable. template<typename _Tp> + _GLIBCXX20_CONSTEXPR inline reference_wrapper<_Tp> ref(_Tp& __t) noexcept { return reference_wrapper<_Tp>(__t); } /// Denotes a const reference should be taken to a variable. template<typename _Tp> + _GLIBCXX20_CONSTEXPR inline reference_wrapper<const _Tp> cref(const _Tp& __t) noexcept { return reference_wrapper<const _Tp>(__t); } @@ -370,12 +378,14 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) /// std::ref overload to prevent wrapping a reference_wrapper template<typename _Tp> + _GLIBCXX20_CONSTEXPR inline reference_wrapper<_Tp> ref(reference_wrapper<_Tp> __t) noexcept { return __t; } /// std::cref overload to prevent wrapping a reference_wrapper template<typename _Tp> + _GLIBCXX20_CONSTEXPR inline reference_wrapper<const _Tp> cref(reference_wrapper<_Tp> __t) noexcept { return { __t.get() }; } diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 113a13b..dad7781 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -112,6 +112,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Mem_fn_base(_MemFunPtr __pmf) noexcept : _M_pmf(__pmf) { } template<typename... _Args> + _GLIBCXX20_CONSTEXPR auto operator()(_Args&&... __args) const noexcept(noexcept( @@ -137,6 +138,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Mem_fn_base(_MemObjPtr __pm) noexcept : _M_pm(__pm) { } template<typename _Tp> + _GLIBCXX20_CONSTEXPR auto operator()(_Tp&& __obj) const noexcept(noexcept(std::__invoke(_M_pm, std::forward<_Tp>(__obj)))) @@ -162,6 +164,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @ingroup functors */ template<typename _Tp, typename _Class> + _GLIBCXX20_CONSTEXPR inline _Mem_fn<_Tp _Class::*> mem_fn(_Tp _Class::* __pm) noexcept { @@ -297,6 +300,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * but not volatile-qualified. This might be a defect in the TR. */ template<typename _CVRef, typename _Tuple> + _GLIBCXX20_CONSTEXPR _Tp& operator()(_CVRef& __arg, _Tuple&) const volatile { return __arg.get(); } @@ -313,6 +317,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { public: template<typename _CVArg, typename... _Args> + _GLIBCXX20_CONSTEXPR auto operator()(_CVArg& __arg, tuple<_Args...>& __tuple) const volatile @@ -328,6 +333,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Invokes the underlying function object __arg by unpacking all // of the arguments in the tuple. template<typename _CVArg, typename... _Args, std::size_t... _Indexes> + _GLIBCXX20_CONSTEXPR auto __call(_CVArg& __arg, tuple<_Args...>& __tuple, const _Index_tuple<_Indexes...>&) const volatile @@ -347,6 +353,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { public: template<typename _Tuple> + _GLIBCXX20_CONSTEXPR _Safe_tuple_element_t<(is_placeholder<_Arg>::value - 1), _Tuple>&& operator()(const volatile _Arg&, _Tuple& __tuple) const volatile { @@ -365,6 +372,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { public: template<typename _CVArg, typename _Tuple> + _GLIBCXX20_CONSTEXPR _CVArg&& operator()(_CVArg&& __arg, _Tuple&) const volatile { return std::forward<_CVArg>(__arg); } @@ -400,6 +408,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call unqualified template<typename _Result, typename... _Args, std::size_t... _Indexes> + _GLIBCXX20_CONSTEXPR _Result __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) { @@ -410,6 +419,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call as const template<typename _Result, typename... _Args, std::size_t... _Indexes> + _GLIBCXX20_CONSTEXPR _Result __call_c(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const { @@ -464,24 +474,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public: template<typename... _Args> - explicit _Bind(const _Functor& __f, _Args&&... __args) + explicit _GLIBCXX20_CONSTEXPR + _Bind(const _Functor& __f, _Args&&... __args) : _M_f(__f), _M_bound_args(std::forward<_Args>(__args)...) { } template<typename... _Args> - explicit _Bind(_Functor&& __f, _Args&&... __args) + explicit _GLIBCXX20_CONSTEXPR + _Bind(_Functor&& __f, _Args&&... __args) : _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...) { } _Bind(const _Bind&) = default; - - _Bind(_Bind&& __b) - : _M_f(std::move(__b._M_f)), _M_bound_args(std::move(__b._M_bound_args)) - { } + _Bind(_Bind&&) = default; // Call unqualified template<typename... _Args, typename _Result = _Res_type<tuple<_Args...>>> + _GLIBCXX20_CONSTEXPR _Result operator()(_Args&&... __args) { @@ -493,6 +503,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call as const template<typename... _Args, typename _Result = _Res_type_cv<tuple<_Args...>, add_const>> + _GLIBCXX20_CONSTEXPR _Result operator()(_Args&&... __args) const { @@ -547,6 +558,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call unqualified template<typename _Res, typename... _Args, std::size_t... _Indexes> + _GLIBCXX20_CONSTEXPR _Res __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) { @@ -556,6 +568,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call as const template<typename _Res, typename... _Args, std::size_t... _Indexes> + _GLIBCXX20_CONSTEXPR _Res __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const { @@ -565,6 +578,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call as volatile template<typename _Res, typename... _Args, std::size_t... _Indexes> + _GLIBCXX20_CONSTEXPR _Res __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) volatile { @@ -574,6 +588,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call as const volatile template<typename _Res, typename... _Args, std::size_t... _Indexes> + _GLIBCXX20_CONSTEXPR _Res __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const volatile @@ -586,23 +601,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef _Result result_type; template<typename... _Args> - explicit _Bind_result(const _Functor& __f, _Args&&... __args) + explicit _GLIBCXX20_CONSTEXPR + _Bind_result(const _Functor& __f, _Args&&... __args) : _M_f(__f), _M_bound_args(std::forward<_Args>(__args)...) { } template<typename... _Args> - explicit _Bind_result(_Functor&& __f, _Args&&... __args) + explicit _GLIBCXX20_CONSTEXPR + _Bind_result(_Functor&& __f, _Args&&... __args) : _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...) { } _Bind_result(const _Bind_result&) = default; - - _Bind_result(_Bind_result&& __b) - : _M_f(std::move(__b._M_f)), _M_bound_args(std::move(__b._M_bound_args)) - { } + _Bind_result(_Bind_result&&) = default; // Call unqualified template<typename... _Args> + _GLIBCXX20_CONSTEXPR result_type operator()(_Args&&... __args) { @@ -613,6 +628,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call as const template<typename... _Args> + _GLIBCXX20_CONSTEXPR result_type operator()(_Args&&... __args) const { @@ -763,7 +779,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @ingroup binders */ template<typename _Func, typename... _BoundArgs> - inline typename + inline _GLIBCXX20_CONSTEXPR typename _Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type bind(_Func&& __f, _BoundArgs&&... __args) { @@ -787,7 +803,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @ingroup binders */ template<typename _Result, typename _Func, typename... _BoundArgs> - inline + inline _GLIBCXX20_CONSTEXPR typename _Bindres_helper<_Result, _Func, _BoundArgs...>::type bind(_Func&& __f, _BoundArgs&&... __args) { @@ -886,7 +902,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION = _Bind_front<decay_t<_Fn>, decay_t<_Args>...>; template<typename _Fn, typename... _Args> - _Bind_front_t<_Fn, _Args...> + constexpr _Bind_front_t<_Fn, _Args...> bind_front(_Fn&& __fn, _Args&&... __args) noexcept(is_nothrow_constructible_v<int, _Bind_front_t<_Fn, _Args...>, _Fn, _Args...>) @@ -910,6 +926,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public: template<typename _Fn2> + constexpr _Not_fn(_Fn2&& __fn, int) : _M_fn(std::forward<_Fn2>(__fn)) { } @@ -922,6 +939,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // and deducing the return type and exception-specification. #define _GLIBCXX_NOT_FN_CALL_OP( _QUALS ) \ template<typename... _Args> \ + _GLIBCXX20_CONSTEXPR \ decltype(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>()) \ operator()(_Args&&... __args) _QUALS \ noexcept(__is_nothrow_invocable<_Fn _QUALS, _Args...>::value \ @@ -966,6 +984,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #define __cpp_lib_not_fn 201603 /// [func.not_fn] Function template not_fn template<typename _Fn> + _GLIBCXX20_CONSTEXPR inline auto not_fn(_Fn&& __fn) noexcept(std::is_nothrow_constructible<std::decay_t<_Fn>, _Fn&&>::value) diff --git a/libstdc++-v3/testsuite/20_util/bind/constexpr.cc b/libstdc++-v3/testsuite/20_util/bind/constexpr.cc new file mode 100644 index 0000000..6761c2c --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bind/constexpr.cc @@ -0,0 +1,43 @@ +// Copyright (C) 2019 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/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include <functional> + +struct add +{ + constexpr int operator()(int i, int j) const { return i + j; } +}; + +constexpr int +test01(int i, int j) +{ + add a; + return std::bind(a, i, std::placeholders::_1)(j); +} + +static_assert( test01(1, 2) == 3 ); + +constexpr int +test02(int i, int j) +{ + return std::bind<int>(add{}, i, std::placeholders::_1)(j); +} + +static_assert( test02(4, 5) == 9 ); diff --git a/libstdc++-v3/testsuite/20_util/function_objects/bind_front/constexpr.cc b/libstdc++-v3/testsuite/20_util/function_objects/bind_front/constexpr.cc new file mode 100644 index 0000000..ee82745 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/function_objects/bind_front/constexpr.cc @@ -0,0 +1,35 @@ +// Copyright (C) 2019 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/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include <functional> + +struct add +{ + constexpr int operator()(int i, int j) const { return i + j; } +}; + +constexpr int +test01(int i, int j) +{ + add a; + return std::bind_front(a, i)(j); +} + +static_assert( test01(1, 2) == 3 ); diff --git a/libstdc++-v3/testsuite/20_util/function_objects/mem_fn/constexpr.cc b/libstdc++-v3/testsuite/20_util/function_objects/mem_fn/constexpr.cc new file mode 100644 index 0000000..6a0d061 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/function_objects/mem_fn/constexpr.cc @@ -0,0 +1,45 @@ +// Copyright (C) 2019 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/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include <functional> + +struct F +{ + int i; + constexpr int add(int j) { return i + j; } +}; + +constexpr int +test01(int i) +{ + F f{i}; + return std::mem_fn(&F::i)(f); +} + +static_assert( test01(2) == 2 ); + +constexpr int +test02(int i, int j) +{ + F f{i}; + return std::mem_fn(&F::add)(&f, j); +} + +static_assert( test02(3, 4) == 7 ); diff --git a/libstdc++-v3/testsuite/20_util/function_objects/not_fn/constexpr.cc b/libstdc++-v3/testsuite/20_util/function_objects/not_fn/constexpr.cc new file mode 100644 index 0000000..1c0e737 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/function_objects/not_fn/constexpr.cc @@ -0,0 +1,35 @@ +// Copyright (C) 2019 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/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include <functional> + +struct F +{ + constexpr bool operator()(int i, int j) const { return i == j; } +}; + +constexpr int +test01(int i, int j) +{ + F f; + return std::not_fn(f)(1, 2); +} + +static_assert( test01(1, 2) ); diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/constexpr.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/constexpr.cc new file mode 100644 index 0000000..8a1c54e --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/constexpr.cc @@ -0,0 +1,45 @@ +// Copyright (C) 2019 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/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include <functional> + +struct F +{ + constexpr int operator()(int i, int j) { return i + j; } + constexpr int operator()(int i, int j) const { return i * j; } +}; + +constexpr int +test01(int i, int j) +{ + F f; + return std::ref(std::ref(f))(i, j); +} + +static_assert( test01(1, 2) == 3 ); + +constexpr int +test02(int i, int j) +{ + F f; + return std::cref(std::cref(f))(i, j); +} + +static_assert( test02(4, 5) == 20 ); |