public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Make std::invoke usable in constant expressions
@ 2019-10-23 19:29 Jonathan Wakely
  2019-10-24 23:22 ` Jonathan Wakely
  0 siblings, 1 reply; 3+ messages in thread
From: Jonathan Wakely @ 2019-10-23 19:29 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 444 bytes --]

	* include/std/functional (invoke): Add constexpr for C++20.
	* include/std/version (__cpp_lib_constexpr_invoke): Define.
	* testsuite/20_util/function_objects/invoke/constexpr.cc: New test.

This is an easy one, because I already made std::__invoke constexpr,
so all that's needed for C++20 is to add _GLIBCXX20_CONSTEXPR to the
public std::invoke function that calls std::__invoke.

Tested powerpc64le-linux, committed to trunk.



[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 3679 bytes --]

commit dae24283df4341aa66f455c8cee6f7935470f7b5
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Oct 23 17:40:42 2019 +0100

    Make std::invoke usable in constant expressions
    
            * include/std/functional (invoke): Add constexpr for C++20.
            * include/std/version (__cpp_lib_constexpr_invoke): Define.
            * testsuite/20_util/function_objects/invoke/constexpr.cc: New test.

diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 7ad29a1a335..113a13b4a37 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -72,19 +72,22 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
-#if __cplusplus > 201402L
-# define __cpp_lib_invoke 201411
+#if __cplusplus >= 201703L
+# define __cpp_lib_invoke 201411L
+# if __cplusplus > 201703L
+#  define __cpp_lib_constexpr_invoke 201907L
+# endif
 
   /// Invoke a callable object.
   template<typename _Callable, typename... _Args>
-    inline invoke_result_t<_Callable, _Args...>
+    inline _GLIBCXX20_CONSTEXPR invoke_result_t<_Callable, _Args...>
     invoke(_Callable&& __fn, _Args&&... __args)
     noexcept(is_nothrow_invocable_v<_Callable, _Args...>)
     {
       return std::__invoke(std::forward<_Callable>(__fn),
 			   std::forward<_Args>(__args)...);
     }
-#endif
+#endif // C++17
 
   template<typename _MemFunPtr,
 	   bool __is_mem_fn = is_member_function_pointer<_MemFunPtr>::value>
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index 21cc28b3450..ccaedd090b0 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -158,6 +158,7 @@
 #endif
 #define __cpp_lib_constexpr 201711L
 #define __cpp_lib_constexpr_algorithms 201806L
+#define __cpp_lib_constexpr_invoke 201907L
 #if __cpp_impl_destroying_delete
 # define __cpp_lib_destroying_delete 201806L
 #endif
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/invoke/constexpr.cc b/libstdc++-v3/testsuite/20_util/function_objects/invoke/constexpr.cc
new file mode 100644
index 00000000000..f65caa21936
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/function_objects/invoke/constexpr.cc
@@ -0,0 +1,38 @@
+// 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>
+
+#ifndef __cpp_lib_constexpr_invoke
+# error "Feature test macro for constexpr invoke is missing"
+#elif __cpp_lib_constexpr_invoke < 201907L
+# error "Feature test macro for constexpr invoke has wrong value"
+#endif
+
+constexpr int inc(int i) { return i + 1; }
+constexpr auto inc_f = &inc;
+static_assert( std::invoke(inc_f, 2) == 3);
+
+struct Dec
+{
+  constexpr int operator()(int i) const { return i - 1; }
+};
+
+static_assert( std::invoke(Dec{}, 5) == 4 );

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Make std::invoke usable in constant expressions
  2019-10-23 19:29 [PATCH] Make std::invoke usable in constant expressions Jonathan Wakely
@ 2019-10-24 23:22 ` Jonathan Wakely
  2019-10-31 23:03   ` Jonathan Wakely
  0 siblings, 1 reply; 3+ messages in thread
From: Jonathan Wakely @ 2019-10-24 23:22 UTC (permalink / raw)
  To: libstdc++, gcc-patches

On 23/10/19 20:28 +0100, Jonathan Wakely wrote:
>	* include/std/functional (invoke): Add constexpr for C++20.
>	* include/std/version (__cpp_lib_constexpr_invoke): Define.
>	* testsuite/20_util/function_objects/invoke/constexpr.cc: New test.
>
>This is an easy one, because I already made std::__invoke constexpr,
>so all that's needed for C++20 is to add _GLIBCXX20_CONSTEXPR to the
>public std::invoke function that calls std::__invoke.

For some reason I thought this change only affected std::invokee, but
P1065R2 affects other functions too. I'll fix those tomorrow.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Make std::invoke usable in constant expressions
  2019-10-24 23:22 ` Jonathan Wakely
@ 2019-10-31 23:03   ` Jonathan Wakely
  0 siblings, 0 replies; 3+ messages in thread
From: Jonathan Wakely @ 2019-10-31 23:03 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 748 bytes --]

On 25/10/19 00:22 +0100, Jonathan Wakely wrote:
>On 23/10/19 20:28 +0100, Jonathan Wakely wrote:
>>	* include/std/functional (invoke): Add constexpr for C++20.
>>	* include/std/version (__cpp_lib_constexpr_invoke): Define.
>>	* testsuite/20_util/function_objects/invoke/constexpr.cc: New test.
>>
>>This is an easy one, because I already made std::__invoke constexpr,
>>so all that's needed for C++20 is to add _GLIBCXX20_CONSTEXPR to the
>>public std::invoke function that calls std::__invoke.
>
>For some reason I thought this change only affected std::invokee, but
>P1065R2 affects other functions too. I'll fix those tomorrow.

Here's the patch for the other parts of P1065R2.

Tested powerpc64le-linux, committed to trunk/



[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 19614 bytes --]

commit 01d276cce42ab417fcd99336ca4b7d75a2861ae8
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Oct 31 22:30:24 2019 +0000

    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.

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<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 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<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 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
+// <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 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
+// <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 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
+// <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 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
+// <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 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
+// <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 );

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-10-31 23:03 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-23 19:29 [PATCH] Make std::invoke usable in constant expressions Jonathan Wakely
2019-10-24 23:22 ` Jonathan Wakely
2019-10-31 23:03   ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).