Index: include/experimental/tuple =================================================================== --- include/experimental/tuple +++ include/experimental/tuple @@ -41,6 +41,7 @@ #if _LIBCPP_STD_VER > 11 # include +# include # include # include <__functional_base> @@ -56,10 +57,10 @@ #endif template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 decltype(auto) __apply_tuple_impl(_Fn && __f, _Tuple && __t, integer_sequence) { - return _VSTD::__invoke( + return _VSTD::__invoke_constexpr( _VSTD::forward<_Fn>(__f), _VSTD::get<_Id>(_VSTD::forward<_Tuple>(__t))... ); Index: include/type_traits =================================================================== --- include/type_traits +++ include/type_traits @@ -3450,6 +3450,51 @@ { }; +// INVOKE metaprogramming support + +template +struct __member_class {}; + +template +struct __member_class<_Ret _Class::*> { typedef _Class type; }; + +template +struct __invoke_mem_type : integral_constant::value ? 1 : + (is_member_object_pointer<_Fp>::value ? 2 : 0)> +{}; + +template ::value != 0> +struct __invoke_is_base_of : false_type {}; + +template +struct __invoke_is_base_of<_Fp, _A0, true> + : is_base_of::type, _A0> +{}; + +template ::type>::type + >::value, + bool = __invoke_is_base_of< + typename remove_cv::type>::type, + typename remove_reference<_A0>::type + >::value> +struct __invoke_enable_if {}; + +template +struct __invoke_enable_if<_Fp, _A0, 1, true> { typedef void _Bullet1; }; + +template +struct __invoke_enable_if<_Fp, _A0, 1, false> { typedef void _Bullet2; }; + +template +struct __invoke_enable_if<_Fp, _A0, 2, true> { typedef void _Bullet3; }; + +template +struct __invoke_enable_if<_Fp, _A0, 2, false> { typedef void _Bullet4; }; + + + // __invoke forward declarations // fall back - none of the bullets @@ -3459,70 +3504,75 @@ __invoke(__any, _Args&& ...__args) -> __nat; -// bullets 1 and 2 - template ::type>::value && - is_base_of::type>::_ClassType>::type, - typename remove_reference<_A0>::type>::value - >::type - > + class = typename __invoke_enable_if<_Fp, _A0>::_Bullet1> _LIBCPP_INLINE_VISIBILITY -auto -__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) +auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) -> decltype((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...)); template ::type>::value && - !is_base_of::type>::_ClassType>::type, - typename remove_reference<_A0>::type>::value - >::type - > + class = typename __invoke_enable_if<_Fp, _A0>::_Bullet2> _LIBCPP_INLINE_VISIBILITY -auto -__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) +auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) -> decltype(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...)); -// bullets 3 and 4 - template ::type>::value && - is_base_of::type>::_ClassType, - typename remove_reference<_A0>::type>::value - >::type - > + class = typename __invoke_enable_if<_Fp, _A0>::_Bullet3> _LIBCPP_INLINE_VISIBILITY -auto -__invoke(_Fp&& __f, _A0&& __a0) +auto __invoke(_Fp&& __f, _A0&& __a0) -> decltype(_VSTD::forward<_A0>(__a0).*__f); template ::type>::value && - !is_base_of::type>::_ClassType, - typename remove_reference<_A0>::type>::value - >::type - > + class = typename __invoke_enable_if<_Fp, _A0>::_Bullet4> _LIBCPP_INLINE_VISIBILITY -auto -__invoke(_Fp&& __f, _A0&& __a0) +auto __invoke(_Fp&& __f, _A0&& __a0) -> decltype((*_VSTD::forward<_A0>(__a0)).*__f); -// bullet 5 - -template +template // bullet 5 _LIBCPP_INLINE_VISIBILITY -auto -__invoke(_Fp&& __f, _Args&& ...__args) +auto __invoke(_Fp&& __f, _Args&& ...__args) -> decltype(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...)); +// __invoke_constexpr + +template ::_Bullet1> +_LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +auto __invoke_constexpr(_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 ::_Bullet2> +_LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +auto __invoke_constexpr(_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 ::_Bullet3> +_LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +auto __invoke_constexpr(_Fp&& __f, _A0&& __a0) + -> decltype(_VSTD::forward<_A0>(__a0).*__f) + { return _VSTD::forward<_A0>(__a0).*__f; } + +template ::_Bullet4> +_LIBCPP_INLINE_VISIBILITY +auto __invoke_constexpr(_Fp&& __f, _A0&& __a0) + -> decltype((*_VSTD::forward<_A0>(__a0)).*__f) + { return (*_VSTD::forward<_A0>(__a0)).*__f; } + +template // bullet 5 +_LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +auto __invoke_constexpr(_Fp&& __f, _Args&& ...__args) + -> decltype(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...)) + { return _VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...); } + // __invokable template 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: * - // // template constexpr decltype(auto) apply(F &&, T &&)