Hi mclow.lists, danalbert, jroelofs,

`std::experimental::apply` requires a constexpr implementation of 
`INVOKE(...)`. Simply marking the current implementation of `__invoke` as 
constexpr will break existing code due to CWG issue #1581. For this reason we 
should add a separate function called `__invoke_constexpr` to be used where 
constexpr is required.

To supply two almost identical `INVOKE(...)` we use the `<__invoke>` header to 
generate the declarations and definitions by defining the required macros and 
including the `<__invoke>` header inline. The `<__invoke>` header can be 
included multiple times.

The macros used are:
* `_LIBCPP_INVOKE_NAME`: The name of the invoke function to be created.
* `_LIBCPP_INVOKE_CONSTEXPR`: The optional `constexpr` decorator for the invoke 
function.
* `_LIBCPP_DECLARE_INVOKE`: Declare the required invoke function.
* `_LIBCPP_DEFINE_INVOKE`: Define the required invoke function.

I chose not to generate invoke functions using macros because of the amount of 
code that would have to be within a macro block. It also is likely to yield bad 
error messages.

This patch also re-enables constexpr support for `std::experimental::apply`.

http://reviews.llvm.org/D9730

Files:
  include/__functional_base
  include/__invoke
  include/experimental/tuple
  include/type_traits
  test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp
  test/std/experimental/utilities/tuple/tuple.apply/ref_qualifiers.pass.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/__functional_base
===================================================================
--- include/__functional_base
+++ include/__functional_base
@@ -360,60 +360,19 @@
 
 // __invoke
 
-// bullets 1 and 2
+#define _LIBCPP_INVOKE_CONSTEXPR
+#define _LIBCPP_INVOKE_NAME __invoke
+#define _LIBCPP_DEFINE_INVOKE
+#include <__invoke>
 
-template <class _Fp, class _A0, class ..._Args,
-            class>
-inline _LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
-    -> decltype((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...))
-{
-    return (_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...);
-}
-
-template <class _Fp, class _A0, class ..._Args,
-            class>
-inline _LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
-    -> decltype(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...))
-{
-    return ((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...);
-}
 
-// bullets 3 and 4
+// __invoke_constexpr
 
-template <class _Fp, class _A0,
-            class>
-inline _LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _A0&& __a0)
-    -> decltype(_VSTD::forward<_A0>(__a0).*__f)
-{
-    return _VSTD::forward<_A0>(__a0).*__f;
-}
-
-template <class _Fp, class _A0,
-            class>
-inline _LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _A0&& __a0)
-    -> decltype((*_VSTD::forward<_A0>(__a0)).*__f)
-{
-    return (*_VSTD::forward<_A0>(__a0)).*__f;
-}
-
-// bullet 5
-
-template <class _Fp, class ..._Args>
-inline _LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _Args&& ...__args)
-    -> decltype(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...))
-{
-    return _VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...);
-}
+#define _LIBCPP_INVOKE_CONSTEXPR _LIBCPP_CONSTEXPR
+#define _LIBCPP_INVOKE_NAME __invoke_constexpr
+#define _LIBCPP_DECLARE_INVOKE
+#define _LIBCPP_DEFINE_INVOKE
+#include <__invoke>
 
 template <class _Tp, class ..._Args>
 struct __invoke_return
Index: include/__invoke
===================================================================
--- /dev/null
+++ include/__invoke
@@ -0,0 +1,164 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_INVOKE_CONSTEXPR
+#error  _LIBCPP_INVOKE_CONSTEXPR must be defined
+#endif
+
+#ifndef _LIBCPP_INVOKE_NAME
+#error  _LIBCPP_INVOKE_NAME must be defined
+#endif
+
+#if !defined(_LIBCPP_DECLARE_INVOKE) && !defined(_LIBCPP_DEFINE_INVOKE)
+#error _LIBCPP_DECLARE_INVOKE or _LIBCPP_DEFINE_INVOKE must be defined \
+       before <__invoke> is included.
+#endif
+
+#ifdef _LIBCPP_DECLARE_INVOKE
+
+// __invoke forward declarations
+
+// fall back - none of the bullets
+
+template <class ..._Args>
+auto
+_LIBCPP_INVOKE_NAME (__any, _Args&& ...__args)
+    -> __nat;
+
+// bullets 1 and 2
+
+template <class _Fp, class _A0, class ..._Args,
+            class = typename enable_if
+            <
+                is_member_function_pointer<typename remove_reference<_Fp>::type>::value &&
+                is_base_of<typename remove_reference<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType>::type,
+                           typename remove_reference<_A0>::type>::value
+            >::type
+         >
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_INVOKE_CONSTEXPR
+auto
+_LIBCPP_INVOKE_NAME (_Fp&& __f, _A0&& __a0, _Args&& ...__args)
+    -> decltype((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...));
+
+template <class _Fp, class _A0, class ..._Args,
+            class = typename enable_if
+            <
+                is_member_function_pointer<typename remove_reference<_Fp>::type>::value &&
+                !is_base_of<typename remove_reference<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType>::type,
+                           typename remove_reference<_A0>::type>::value
+            >::type
+         >
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_INVOKE_CONSTEXPR
+auto
+_LIBCPP_INVOKE_NAME (_Fp&& __f, _A0&& __a0, _Args&& ...__args)
+    -> decltype(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...));
+
+// bullets 3 and 4
+
+template <class _Fp, class _A0,
+            class = typename enable_if
+            <
+                is_member_object_pointer<typename remove_reference<_Fp>::type>::value &&
+                is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType,
+                           typename remove_reference<_A0>::type>::value
+            >::type
+         >
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_INVOKE_CONSTEXPR
+auto
+_LIBCPP_INVOKE_NAME (_Fp&& __f, _A0&& __a0)
+    -> decltype(_VSTD::forward<_A0>(__a0).*__f);
+
+template <class _Fp, class _A0,
+            class = typename enable_if
+            <
+                is_member_object_pointer<typename remove_reference<_Fp>::type>::value &&
+                !is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType,
+                           typename remove_reference<_A0>::type>::value
+            >::type
+         >
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_INVOKE_CONSTEXPR
+auto
+_LIBCPP_INVOKE_NAME (_Fp&& __f, _A0&& __a0)
+    -> decltype((*_VSTD::forward<_A0>(__a0)).*__f);
+
+// bullet 5
+
+template <class _Fp, class ..._Args>
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_INVOKE_CONSTEXPR
+auto
+_LIBCPP_INVOKE_NAME (_Fp&& __f, _Args&& ...__args)
+    -> decltype(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...));
+
+
+#endif // _LIBCPP_DECLARE_INVOKE
+
+#ifdef _LIBCPP_DEFINE_INVOKE
+
+// bullets 1 and 2
+
+template <class _Fp, class _A0, class ..._Args,
+            class>
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_INVOKE_CONSTEXPR
+auto
+_LIBCPP_INVOKE_NAME (_Fp&& __f, _A0&& __a0, _Args&& ...__args)
+    -> decltype((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...))
+{
+    return (_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...);
+}
+
+template <class _Fp, class _A0, class ..._Args,
+            class>
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_INVOKE_CONSTEXPR
+auto
+_LIBCPP_INVOKE_NAME (_Fp&& __f, _A0&& __a0, _Args&& ...__args)
+    -> decltype(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...))
+{
+    return ((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...);
+}
+
+// bullets 3 and 4
+
+template <class _Fp, class _A0,
+            class>
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_INVOKE_CONSTEXPR
+auto
+_LIBCPP_INVOKE_NAME (_Fp&& __f, _A0&& __a0)
+    -> decltype(_VSTD::forward<_A0>(__a0).*__f)
+{
+    return _VSTD::forward<_A0>(__a0).*__f;
+}
+
+template <class _Fp, class _A0,
+            class>
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_INVOKE_CONSTEXPR
+auto
+_LIBCPP_INVOKE_NAME (_Fp&& __f, _A0&& __a0)
+    -> decltype((*_VSTD::forward<_A0>(__a0)).*__f)
+{
+    return (*_VSTD::forward<_A0>(__a0)).*__f;
+}
+
+// bullet 5
+
+template <class _Fp, class ..._Args>
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_INVOKE_CONSTEXPR
+auto
+_LIBCPP_INVOKE_NAME (_Fp&& __f, _Args&& ...__args)
+    -> decltype(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...))
+{
+    return _VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...);
+}
+
+#endif // _LIBCPP_DEFINE_INVOKE
+
+#undef _LIBCPP_INVOKE_CONSTEXPR
+#undef _LIBCPP_INVOKE_NAME
+#undef _LIBCPP_DECLARE_INVOKE
+#undef _LIBCPP_DEFINE_INVOKE
Index: include/experimental/tuple
===================================================================
--- include/experimental/tuple
+++ include/experimental/tuple
@@ -56,17 +56,17 @@
 #endif
 
 template <class _Fn, class _Tuple, size_t ..._Id>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
 decltype(auto) __apply_tuple_impl(_Fn && __f, _Tuple && __t,
                                   integer_sequence<size_t, _Id...>) {
-    return _VSTD::__invoke(
+    return _VSTD::__invoke_constexpr(
         _VSTD::forward<_Fn>(__f),
         _VSTD::get<_Id>(_VSTD::forward<_Tuple>(__t))...
     );
 }
 
 template <class _Fn, class _Tuple>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
 decltype(auto) apply(_Fn && __f, _Tuple && __t) {
     return _VSTD_LFTS::__apply_tuple_impl(
         _VSTD::forward<_Fn>(__f), _VSTD::forward<_Tuple>(__t),
Index: include/type_traits
===================================================================
--- include/type_traits
+++ include/type_traits
@@ -3429,78 +3429,10 @@
 {
 };
 
-// __invoke forward declarations
-
-// fall back - none of the bullets
-
-template <class ..._Args>
-auto
-__invoke(__any, _Args&& ...__args)
-    -> __nat;
-
-// bullets 1 and 2
-
-template <class _Fp, class _A0, class ..._Args,
-            class = typename enable_if
-            <
-                is_member_function_pointer<typename remove_reference<_Fp>::type>::value &&
-                is_base_of<typename remove_reference<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType>::type,
-                           typename remove_reference<_A0>::type>::value
-            >::type
-         >
-_LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
-    -> decltype((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...));
-
-template <class _Fp, class _A0, class ..._Args,
-            class = typename enable_if
-            <
-                is_member_function_pointer<typename remove_reference<_Fp>::type>::value &&
-                !is_base_of<typename remove_reference<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType>::type,
-                           typename remove_reference<_A0>::type>::value
-            >::type
-         >
-_LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
-    -> decltype(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...));
-
-// bullets 3 and 4
-
-template <class _Fp, class _A0,
-            class = typename enable_if
-            <
-                is_member_object_pointer<typename remove_reference<_Fp>::type>::value &&
-                is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType,
-                           typename remove_reference<_A0>::type>::value
-            >::type
-         >
-_LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _A0&& __a0)
-    -> decltype(_VSTD::forward<_A0>(__a0).*__f);
-
-template <class _Fp, class _A0,
-            class = typename enable_if
-            <
-                is_member_object_pointer<typename remove_reference<_Fp>::type>::value &&
-                !is_base_of<typename __member_pointer_traits<typename remove_reference<_Fp>::type>::_ClassType,
-                           typename remove_reference<_A0>::type>::value
-            >::type
-         >
-_LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _A0&& __a0)
-    -> decltype((*_VSTD::forward<_A0>(__a0)).*__f);
-
-// bullet 5
-
-template <class _Fp, class ..._Args>
-_LIBCPP_INLINE_VISIBILITY
-auto
-__invoke(_Fp&& __f, _Args&& ...__args)
-    -> decltype(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...));
+#define _LIBCPP_INVOKE_CONSTEXPR
+#define _LIBCPP_INVOKE_NAME __invoke
+#define _LIBCPP_DECLARE_INVOKE
+#include <__invoke>
 
 // __invokable
 
Index: test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp
===================================================================
--- test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp
+++ test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp
@@ -9,11 +9,6 @@
 
 // UNSUPPORTED: c++98, c++03, c++11
 
-// TODO(ericwf)
-// constexpr support temporarily reverted due to bug:
-// https://llvm.org/bugs/show_bug.cgi?id=23141
-// XFAIL: *
-
 // <experimental/tuple>
 
 // template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)
Index: test/std/experimental/utilities/tuple/tuple.apply/ref_qualifiers.pass.cpp
===================================================================
--- test/std/experimental/utilities/tuple/tuple.apply/ref_qualifiers.pass.cpp
+++ test/std/experimental/utilities/tuple/tuple.apply/ref_qualifiers.pass.cpp
@@ -32,8 +32,6 @@
 
 int main()
 {
-// TODO(ericwf): Re-enable constexpr support
-/*
     {
         constexpr func_obj f;
         constexpr std::tuple<> tp;
@@ -41,7 +39,6 @@
         static_assert(1 == ex::apply(static_cast<func_obj const &>(f), tp), "");
         static_assert(2 == ex::apply(static_cast<func_obj const &&>(f), tp), "");
     }
-*/
     {
         func_obj f;
         std::tuple<> tp;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to