From 3e9f67e6a2c13e7e78d1e34dadfdc8d96176e9fe Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Sat, 6 Aug 2016 01:06:02 +0100 Subject: [PATCH] Add std::apply for C++17 * doc/xml/manual/status_cxx2017.xml: Add missing LFTSv2 features. * doc/html/manual/status.html: Regenerate. * include/Makefile.am: Add new header. * include/Makefile.in: Regenerate. * include/bits/invoke.h: New header. (__invoke): Make constexpr. Add && to types in exception specification. * include/experimental/tuple (apply, __apply_impl): Fix non-reserved names. Include and use std::__invoke. * include/std/functional (__invfwd, __invoke_impl, __invoke): Move to new header. (invoke): Add && to types in exception specification. * include/std/tuple (apply, __apply_impl): Define for C++17. * testsuite/20_util/tuple/apply/1.cc: New test. * testsuite/20_util/tuple/element_access/get_neg.cc: Adjust dg-error lineno. From-SVN: r239183 --- libstdc++-v3/ChangeLog | 18 +++ libstdc++-v3/doc/html/manual/status.html | 14 ++- .../doc/xml/manual/status_cxx2017.xml | 35 ++++++ libstdc++-v3/include/Makefile.am | 1 + libstdc++-v3/include/Makefile.in | 1 + libstdc++-v3/include/bits/invoke.h | 104 ++++++++++++++++++ libstdc++-v3/include/experimental/tuple | 15 ++- libstdc++-v3/include/std/functional | 52 +-------- libstdc++-v3/include/std/tuple | 22 ++++ .../testsuite/20_util/tuple/apply/1.cc | 67 +++++++++++ .../20_util/tuple/element_access/get_neg.cc | 2 +- 11 files changed, 271 insertions(+), 60 deletions(-) create mode 100644 libstdc++-v3/include/bits/invoke.h create mode 100644 libstdc++-v3/testsuite/20_util/tuple/apply/1.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index e6bf4c95d70f..81fb9e38ba74 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,21 @@ +2016-08-06 Jonathan Wakely + + * doc/xml/manual/status_cxx2017.xml: Add missing LFTSv2 features. + * doc/html/manual/status.html: Regenerate. + * include/Makefile.am: Add new header. + * include/Makefile.in: Regenerate. + * include/bits/invoke.h: New header. + (__invoke): Make constexpr. Add && to types in exception specification. + * include/experimental/tuple (apply, __apply_impl): Fix non-reserved + names. Include and use std::__invoke. + * include/std/functional (__invfwd, __invoke_impl, __invoke): Move to + new header. + (invoke): Add && to types in exception specification. + * include/std/tuple (apply, __apply_impl): Define for C++17. + * testsuite/20_util/tuple/apply/1.cc: New test. + * testsuite/20_util/tuple/element_access/get_neg.cc: Adjust dg-error + lineno. + 2016-08-05 Jonathan Wakely * doc/xml/manual/status_cxx2017.xml: Correct shared_from_this status. diff --git a/libstdc++-v3/doc/html/manual/status.html b/libstdc++-v3/doc/html/manual/status.html index c690cf3ac910..35b31c1720db 100644 --- a/libstdc++-v3/doc/html/manual/status.html +++ b/libstdc++-v3/doc/html/manual/status.html @@ -515,7 +515,19 @@ Feature-testing recommendations for C++. P0220R1 - No __has_include(<memory_resource>) Constant View: A proposal for a std::as_const helper function template + No __has_include(<memory_resource>) Library Fundamentals V1 TS Components: apply + + P0220R1 + + 7 __cpp_lib_apply >= 201603 Library Fundamentals V1 TS Components: shared_ptr<T[]> + + P0220R1 + + No __cpp_lib_shared_ptr_arrays >= 201603 Library Fundamentals V1 TS Components: Searchers + + P0220R1 + + No __cpp_lib_boyer_moore_searcher >= 201603 Constant View: A proposal for a std::as_const helper function template P0007R1 diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml index 02aec2571f9e..55e3ff59d972 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml @@ -148,6 +148,41 @@ Feature-testing recommendations for C++. __has_include(<memory_resource>) + + Library Fundamentals V1 TS Components: apply + + + P0220R1 + + + 7 + __cpp_lib_apply >= 201603 + + + + + Library Fundamentals V1 TS Components: shared_ptr<T[]> + + + P0220R1 + + + No + __cpp_lib_shared_ptr_arrays >= 201603 + + + + + Library Fundamentals V1 TS Components: Searchers + + + P0220R1 + + + No + __cpp_lib_boyer_moore_searcher >= 201603 + + Constant View: A proposal for a std::as_const helper function template diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index e2c4f63d623a..ea992f05319a 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -112,6 +112,7 @@ bits_headers = \ ${bits_srcdir}/hashtable.h \ ${bits_srcdir}/hashtable_policy.h \ ${bits_srcdir}/indirect_array.h \ + ${bits_srcdir}/invoke.h \ ${bits_srcdir}/ios_base.h \ ${bits_srcdir}/istream.tcc \ ${bits_srcdir}/list.tcc \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index 882ff14557da..b30eeae5f49a 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -402,6 +402,7 @@ bits_headers = \ ${bits_srcdir}/hashtable.h \ ${bits_srcdir}/hashtable_policy.h \ ${bits_srcdir}/indirect_array.h \ + ${bits_srcdir}/invoke.h \ ${bits_srcdir}/ios_base.h \ ${bits_srcdir}/istream.tcc \ ${bits_srcdir}/list.tcc \ diff --git a/libstdc++-v3/include/bits/invoke.h b/libstdc++-v3/include/bits/invoke.h new file mode 100644 index 000000000000..60405b5cc87b --- /dev/null +++ b/libstdc++-v3/include/bits/invoke.h @@ -0,0 +1,104 @@ +// Implementation of INVOKE -*- C++ -*- + +// Copyright (C) 2016 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/invoke.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_INVOKE_H +#define _GLIBCXX_INVOKE_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + // Used by __invoke_impl instead of std::forward<_Tp> so that a + // reference_wrapper is converted to an lvalue-reference. + template::type> + constexpr _Up&& + __invfwd(typename remove_reference<_Tp>::type& __t) noexcept + { return static_cast<_Up&&>(__t); } + + template + constexpr _Res + __invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args) + { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); } + + template + constexpr _Res + __invoke_impl(__invoke_memfun_ref, _MemFun&& __f, _Tp&& __t, + _Args&&... __args) + { return (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...); } + + template + constexpr _Res + __invoke_impl(__invoke_memfun_deref, _MemFun&& __f, _Tp&& __t, + _Args&&... __args) + { + return ((*std::forward<_Tp>(__t)).*__f)(std::forward<_Args>(__args)...); + } + + template + constexpr _Res + __invoke_impl(__invoke_memobj_ref, _MemPtr&& __f, _Tp&& __t) + { return __invfwd<_Tp>(__t).*__f; } + + template + constexpr _Res + __invoke_impl(__invoke_memobj_deref, _MemPtr&& __f, _Tp&& __t) + { return (*std::forward<_Tp>(__t)).*__f; } + + /// Invoke a callable object. + template + constexpr typename result_of<_Callable&&(_Args&&...)>::type + __invoke(_Callable&& __fn, _Args&&... __args) + noexcept(__is_nothrow_callable<_Callable(_Args&&...)>::value) + { + using __result_of = result_of<_Callable&&(_Args&&...)>; + using __type = typename __result_of::type; + using __tag = typename __result_of::__invoke_type; + return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_INVOKE_H diff --git a/libstdc++-v3/include/experimental/tuple b/libstdc++-v3/include/experimental/tuple index 81e91bda3735..bfa1ed18f9e1 100644 --- a/libstdc++-v3/include/experimental/tuple +++ b/libstdc++-v3/include/experimental/tuple @@ -36,7 +36,7 @@ #else #include -#include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -54,20 +54,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template constexpr decltype(auto) - __apply_impl(_Fn&& f, _Tuple&& t, std::index_sequence<_Idx...>) + __apply_impl(_Fn&& __f, _Tuple&& __t, std::index_sequence<_Idx...>) { - using _Wrap = _Maybe_wrap_member_pointer>; - return _Wrap::__do_wrap(std::forward<_Fn>(f))( - std::get<_Idx>(std::forward<_Tuple>(t))...); + return std::__invoke(std::forward<_Fn>(__f), + std::get<_Idx>(std::forward<_Tuple>(__t))...); } template constexpr decltype(auto) - apply(_Fn&& f, _Tuple&& t) + apply(_Fn&& __f, _Tuple&& __t) { using _Indices = - std::make_index_sequence>::value>; - return __apply_impl(std::forward<_Fn>(f), std::forward<_Tuple>(t), + std::make_index_sequence>>; + return __apply_impl(std::forward<_Fn>(__f), std::forward<_Tuple>(__t), _Indices{}); } diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 4ca32c3ef077..1de914e4a2ef 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -56,6 +56,7 @@ #include #include #include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -184,55 +185,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Weak_result_type_impl::type> { }; - // Used by __invoke_impl instead of std::forward<_Tp> so that a - // reference_wrapper is converted to an lvalue-reference. - template::type> - inline _Up&& - __invfwd(typename remove_reference<_Tp>::type& __t) noexcept - { return static_cast<_Up&&>(__t); } - - template - inline _Res - __invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args) - { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); } - - template - inline _Res - __invoke_impl(__invoke_memfun_ref, _MemFun&& __f, _Tp&& __t, - _Args&&... __args) - { return (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...); } - - template - inline _Res - __invoke_impl(__invoke_memfun_deref, _MemFun&& __f, _Tp&& __t, - _Args&&... __args) - { - return ((*std::forward<_Tp>(__t)).*__f)(std::forward<_Args>(__args)...); - } - - template - inline _Res - __invoke_impl(__invoke_memobj_ref, _MemPtr&& __f, _Tp&& __t) - { return __invfwd<_Tp>(__t).*__f; } - - template - inline _Res - __invoke_impl(__invoke_memobj_deref, _MemPtr&& __f, _Tp&& __t) - { return (*std::forward<_Tp>(__t)).*__f; } - - /// Invoke a callable object. - template - inline typename result_of<_Callable&&(_Args&&...)>::type - __invoke(_Callable&& __fn, _Args&&... __args) - noexcept(__is_nothrow_callable<_Callable(_Args...)>::value) - { - using __result_of = result_of<_Callable&&(_Args&&...)>; - using __type = typename __result_of::type; - using __tag = typename __result_of::__invoke_type; - return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), - std::forward<_Args>(__args)...); - } - #if __cplusplus > 201402L # define __cpp_lib_invoke 201411 @@ -240,7 +192,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline result_of_t<_Callable&&(_Args&&...)> invoke(_Callable&& __fn, _Args&&... __args) - noexcept(is_nothrow_callable_v<_Callable(_Args...)>) + noexcept(is_nothrow_callable_v<_Callable(_Args&&...)>) { return std::__invoke(std::forward<_Callable>(__fn), std::forward<_Args>(__args)...); diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 484cb4822f24..b9074cb1bd90 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -38,6 +38,7 @@ #include #include #include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -1635,6 +1636,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...) { } +#if __cplusplus > 201402L +# define __cpp_lib_apply 201603 + + template + constexpr decltype(auto) + __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>) + { + return std::__invoke(std::forward<_Fn>(__f), + std::get<_Idx>(std::forward<_Tuple>(__t))...); + } + + template + constexpr decltype(auto) + apply(_Fn&& __f, _Tuple&& __t) + { + using _Indices = make_index_sequence>>; + return __apply_impl(std::forward<_Fn>(__f), std::forward<_Tuple>(__t), + _Indices{}); + } +#endif // C++17 + /// @} _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/testsuite/20_util/tuple/apply/1.cc b/libstdc++-v3/testsuite/20_util/tuple/apply/1.cc new file mode 100644 index 000000000000..c12309cd253d --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/apply/1.cc @@ -0,0 +1,67 @@ +// Copyright (C) 2014-2016 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++17" } + +#include +#include + +#if __cpp_lib_apply < 201603 +# error "__cpp_lib_apply < 201603" +#endif + +void +test01() +{ + auto t = std::make_tuple(1, '2', 3.0); + std::apply( [&](int& i, char& c, double& d) { + VERIFY(&i == &std::get(t)); + VERIFY(&c == &std::get(t)); + VERIFY(&d == &std::get(t)); + }, t); +} + +constexpr int func(int i, int j) { return i + j; } + +void +test02() +{ + constexpr auto t = std::make_tuple(1, 2); + constexpr int i = std::apply(func, t); + VERIFY( i == 3 ); +} + +struct F +{ + int f(int i, int j) const { return i + j; } +}; + +void +test03() +{ + auto t = std::make_tuple(F{}, 1, 2); + int r = std::apply(&F::f, t); + VERIFY( r == 3 ); +} + +int +main() +{ + test01(); + test02(); + test03(); +} diff --git a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc index 95ff697ae7a7..5bcf5761c360 100644 --- a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc +++ b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc @@ -17,7 +17,7 @@ // { dg-options "-fno-show-column" } // { dg-do compile { target c++14 } } -// { dg-error "in range" "" { target *-*-* } 1279 } +// { dg-error "in range" "" { target *-*-* } 1280 } #include -- 2.39.2