From 2670a7aa8f2680af6c113a6dec97f21d5715c809 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 31 Oct 2019 23:03:22 +0000 Subject: [PATCH] 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 --- libstdc++-v3/ChangeLog | 10 ++++ libstdc++-v3/include/bits/refwrap.h | 10 ++++ libstdc++-v3/include/std/functional | 49 +++++++++++++------ .../testsuite/20_util/bind/constexpr.cc | 43 ++++++++++++++++ .../function_objects/bind_front/constexpr.cc | 35 +++++++++++++ .../function_objects/mem_fn/constexpr.cc | 45 +++++++++++++++++ .../function_objects/not_fn/constexpr.cc | 35 +++++++++++++ .../20_util/reference_wrapper/constexpr.cc | 45 +++++++++++++++++ 8 files changed, 257 insertions(+), 15 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/bind/constexpr.cc create mode 100644 libstdc++-v3/testsuite/20_util/function_objects/bind_front/constexpr.cc create mode 100644 libstdc++-v3/testsuite/20_util/function_objects/mem_fn/constexpr.cc create mode 100644 libstdc++-v3/testsuite/20_util/function_objects/not_fn/constexpr.cc create mode 100644 libstdc++-v3/testsuite/20_util/reference_wrapper/constexpr.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 1004d76a77d..02901110493 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,15 @@ 2019-10-31 Jonathan Wakely + * 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 e810988cd4f..41e4653f246 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> @@ -315,6 +317,7 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) // 3041. Unnecessary decay in reference_wrapper template, 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 + _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 + _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 + _GLIBCXX20_CONSTEXPR inline reference_wrapper cref(const _Tp& __t) noexcept { return reference_wrapper(__t); } @@ -370,12 +378,14 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) /// std::ref overload to prevent wrapping a reference_wrapper template + _GLIBCXX20_CONSTEXPR inline reference_wrapper<_Tp> ref(reference_wrapper<_Tp> __t) noexcept { return __t; } /// std::cref overload to prevent wrapping a reference_wrapper template + _GLIBCXX20_CONSTEXPR inline reference_wrapper cref(reference_wrapper<_Tp> __t) noexcept { return { __t.get() }; } diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 113a13b4a37..dad7781378b 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 + _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 + _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 + _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 + _GLIBCXX20_CONSTEXPR _Tp& operator()(_CVRef& __arg, _Tuple&) const volatile { return __arg.get(); } @@ -313,6 +317,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { public: template + _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 + _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 + _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 + _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 + _GLIBCXX20_CONSTEXPR _Result __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) { @@ -410,6 +419,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call as const template + _GLIBCXX20_CONSTEXPR _Result __call_c(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const { @@ -464,24 +474,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public: template - 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 - 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>> + _GLIBCXX20_CONSTEXPR _Result operator()(_Args&&... __args) { @@ -493,6 +503,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call as const template, add_const>> + _GLIBCXX20_CONSTEXPR _Result operator()(_Args&&... __args) const { @@ -547,6 +558,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call unqualified template + _GLIBCXX20_CONSTEXPR _Res __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) { @@ -556,6 +568,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call as const template + _GLIBCXX20_CONSTEXPR _Res __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const { @@ -565,6 +578,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call as volatile template + _GLIBCXX20_CONSTEXPR _Res __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) volatile { @@ -574,6 +588,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call as const volatile template + _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 - 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 - 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 + _GLIBCXX20_CONSTEXPR result_type operator()(_Args&&... __args) { @@ -613,6 +628,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Call as const template + _GLIBCXX20_CONSTEXPR result_type operator()(_Args&&... __args) const { @@ -763,7 +779,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @ingroup binders */ template - 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 - 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<_Args>...>; template - _Bind_front_t<_Fn, _Args...> + constexpr _Bind_front_t<_Fn, _Args...> bind_front(_Fn&& __fn, _Args&&... __args) noexcept(is_nothrow_constructible_v, _Fn, _Args...>) @@ -910,6 +926,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public: template + 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 \ + _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 + _GLIBCXX20_CONSTEXPR inline auto not_fn(_Fn&& __fn) noexcept(std::is_nothrow_constructible, _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 00000000000..6761c2c92a1 --- /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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +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(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 00000000000..ee82745ddb7 --- /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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +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 00000000000..6a0d0616baa --- /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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +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 00000000000..1c0e737fb7d --- /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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +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 00000000000..8a1c54eea7f --- /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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +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 ); -- 2.30.2