From patchwork Fri Aug 5 23:57:46 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 656320 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3s5kK70pJ8z9ssP for ; Sat, 6 Aug 2016 09:58:17 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=Y4qTFGGa; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=c+bRepXe5ohGAUuBe+SRUzQAx97b2YTQb9pVduyymXS3w/n5EKyzI CJBm1tQXKp3OCgUpLLHiBz3hHdg4VGNL6NFYpVv+zAzf/tj99PlZ9UGXCUvUPfni e8xVHxAj4wMLedl7QMW7vcWVNDrUi7f8p3acWQE+3R7YKNn9SbwTlg= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=k3w6FiP/YuCcMPsNiv7VTjSzE+A=; b=Y4qTFGGaQXYbRkkfCwze 9cSSTG7UTvOl5ctuPfUMN/AUy+kAiH/RYrVJ84pCUvwlTkZ0D1ByEeXA1LZOUzcl 4cL7aa+PMd7WchoDz/oHM3MUaquoRdonQ6vI469FLJRkNDCnSi1rsRxjXB+BHYZO HxsKfUU/qFYKMLRxoUj2T08= Received: (qmail 50118 invoked by alias); 5 Aug 2016 23:58:00 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 50098 invoked by uid 89); 5 Aug 2016 23:57:59 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.1 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=Implementation, hashtableh, circular, Components X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 05 Aug 2016 23:57:49 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8AAEF811A2; Fri, 5 Aug 2016 23:57:47 +0000 (UTC) Received: from localhost (ovpn-116-26.ams2.redhat.com [10.36.116.26]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u75Nvkkg027422; Fri, 5 Aug 2016 19:57:47 -0400 Date: Sat, 6 Aug 2016 00:57:46 +0100 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [PATCH] Add std::apply for C++17 Message-ID: <20160805235746.GA16057@redhat.com> MIME-Version: 1.0 Content-Disposition: inline X-Clacks-Overhead: GNU Terry Pratchett User-Agent: Mutt/1.6.2 (2016-07-01) To avoid a circular dependency between and I've moved std::__invoke to its own header. In order to use std::__invoke in std::apply it needs to be constexpr, which is easy, but the standard says that std::invoke isn't constexpr. So we have to intentionally disallow std::invoke in constant expressions even though it's implemented purely in terms of a constexpr function. Expect a ballot comment about that. This also fixes a bug in the exception specifications of std::__invoke and std::invoke, where the function type used as the template argument to __is_nothrow_callable would have decayed its argument types, so we need && there to prevent that. * 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. Tested powerpc64-linux, committed to trunk. commit 031d50fec36dd04c1e086ab7060d497a441f0d8a Author: Jonathan Wakely Date: Fri Aug 5 17:27:46 2016 +0100 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. diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml index 02aec25..55e3ff5 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml @@ -149,6 +149,41 @@ Feature-testing recommendations for C++. + 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 e2c4f63..ea992f0 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/bits/invoke.h b/libstdc++-v3/include/bits/invoke.h new file mode 100644 index 0000000..60405b5 --- /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 81e91bd..bfa1ed1 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 4ca32c3..1de914e 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 484cb48..b9074cb 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 0000000..c12309c --- /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 95ff697..5bcf576 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