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.
{
_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>>
// 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)))
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
{
/// 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); }
/// 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() }; }
_Mem_fn_base(_MemFunPtr __pmf) noexcept : _M_pmf(__pmf) { }
template<typename... _Args>
+ _GLIBCXX20_CONSTEXPR
auto
operator()(_Args&&... __args) const
noexcept(noexcept(
_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))))
* @ingroup functors
*/
template<typename _Tp, typename _Class>
+ _GLIBCXX20_CONSTEXPR
inline _Mem_fn<_Tp _Class::*>
mem_fn(_Tp _Class::* __pm) noexcept
{
* 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(); }
{
public:
template<typename _CVArg, typename... _Args>
+ _GLIBCXX20_CONSTEXPR
auto
operator()(_CVArg& __arg,
tuple<_Args...>& __tuple) const volatile
// 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
{
public:
template<typename _Tuple>
+ _GLIBCXX20_CONSTEXPR
_Safe_tuple_element_t<(is_placeholder<_Arg>::value - 1), _Tuple>&&
operator()(const volatile _Arg&, _Tuple& __tuple) const volatile
{
{
public:
template<typename _CVArg, typename _Tuple>
+ _GLIBCXX20_CONSTEXPR
_CVArg&&
operator()(_CVArg&& __arg, _Tuple&) const volatile
{ return std::forward<_CVArg>(__arg); }
// Call unqualified
template<typename _Result, typename... _Args, std::size_t... _Indexes>
+ _GLIBCXX20_CONSTEXPR
_Result
__call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>)
{
// Call as const
template<typename _Result, typename... _Args, std::size_t... _Indexes>
+ _GLIBCXX20_CONSTEXPR
_Result
__call_c(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const
{
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)
{
// Call as const
template<typename... _Args,
typename _Result = _Res_type_cv<tuple<_Args...>, add_const>>
+ _GLIBCXX20_CONSTEXPR
_Result
operator()(_Args&&... __args) const
{
// Call unqualified
template<typename _Res, typename... _Args, std::size_t... _Indexes>
+ _GLIBCXX20_CONSTEXPR
_Res
__call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>)
{
// Call as const
template<typename _Res, typename... _Args, std::size_t... _Indexes>
+ _GLIBCXX20_CONSTEXPR
_Res
__call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const
{
// Call as volatile
template<typename _Res, typename... _Args, std::size_t... _Indexes>
+ _GLIBCXX20_CONSTEXPR
_Res
__call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) volatile
{
// 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
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)
{
// Call as const
template<typename... _Args>
+ _GLIBCXX20_CONSTEXPR
result_type
operator()(_Args&&... __args) const
{
* @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)
{
* @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)
{
= _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...>)
public:
template<typename _Fn2>
+ constexpr
_Not_fn(_Fn2&& __fn, int)
: _M_fn(std::forward<_Fn2>(__fn)) { }
// 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 \
#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)
--- /dev/null
+// 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 );
--- /dev/null
+// 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 );
--- /dev/null
+// 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 );
--- /dev/null
+// 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) );
--- /dev/null
+// 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 );