From patchwork Tue Sep 13 00:09:19 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Carlini X-Patchwork-Id: 114429 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]) by ozlabs.org (Postfix) with SMTP id B0B26B71C0 for ; Tue, 13 Sep 2011 10:10:04 +1000 (EST) Received: (qmail 16589 invoked by alias); 13 Sep 2011 00:09:56 -0000 Received: (qmail 16551 invoked by uid 22791); 13 Sep 2011 00:09:48 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE X-Spam-Check-By: sourceware.org Received: from smtp209.alice.it (HELO smtp209.alice.it) (82.57.200.105) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 13 Sep 2011 00:09:28 +0000 Received: from [192.168.1.4] (79.50.51.48) by smtp209.alice.it (8.5.124.08) id 4E2CB71203F23E67; Tue, 13 Sep 2011 02:09:25 +0200 Message-ID: <4E6E9F2F.6010707@oracle.com> Date: Tue, 13 Sep 2011 02:09:19 +0200 From: Paolo Carlini User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:6.0) Gecko/20110812 Thunderbird/6.0 MIME-Version: 1.0 To: "gcc-patches@gcc.gnu.org" CC: libstdc++ Subject: [v3] Declare std::tuple_cat constexpr (+ all std::get) X-IsSubscribed: yes 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 Hi, Daniel kindly helped adjusting to enable constexpr for std::tuple_cat. At the same time all the std::get overloads, for std::pair and std::array too. Tested x86_64-linux, committed. Thanks, Paolo. //////////////////////////// 2011-09-12 Daniel Krugler Paolo Carlini * include/std/tuple (_Head_base<>::_M_head, _Head_base<>::_M_tail, _Tuple_impl<>::_M_head, _Tuple_impl<>::_M_tail): Change to static constexpr functions; adjust everywhere. (__get_helper, get): Declare constexpr all three overloads. (tuple_cat): Declare constexpr; use late return type to improve error messages. * include/std/utility (__pair_get<>::__get, __pair_get<>::__move_get, __pair_get<>::__const_get, get): Declare all constexpr. * include/std/array (get): Likewise. * testsuite/20_util/tuple/creation_functions/constexpr.cc: Re-enable tuple_cat test. * testsuite/23_containers/array/constexpr_get.cc: New. * testsuite/20_util/tuple/element_access/constexpr_get.cc: Likewise. * testsuite/20_util/pair/constexpr_get.cc: Likewise. * testsuite/20_util/weak_ptr/comparison/cmp_neg.cc: Adjust dg-error line number. Index: include/std/tuple =================================================================== --- include/std/tuple (revision 178791) +++ include/std/tuple (working copy) @@ -140,11 +140,11 @@ _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { } - _Head& - _M_head() noexcept { return *this; } + static constexpr _Head& + _M_head(_Head_base& __b) noexcept { return __b; } - constexpr const _Head& - _M_head() const noexcept { return *this; } + static constexpr const _Head& + _M_head(const _Head_base& __b) noexcept { return __b; } }; template @@ -186,13 +186,13 @@ _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { } - _Head& - _M_head() noexcept { return _M_head_impl; } + static constexpr _Head& + _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; } - constexpr const _Head& - _M_head() const noexcept { return _M_head_impl; } + static constexpr const _Head& + _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; } - _Head _M_head_impl; + _Head _M_head_impl; }; /** @@ -245,17 +245,17 @@ typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited; typedef _Head_base<_Idx, _Head, std::is_empty<_Head>::value> _Base; - _Head& - _M_head() noexcept { return _Base::_M_head(); } + static constexpr _Head& + _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } - constexpr const _Head& - _M_head() const noexcept { return _Base::_M_head(); } + static constexpr const _Head& + _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } - _Inherited& - _M_tail() noexcept { return *this; } + static constexpr _Inherited& + _M_tail(_Tuple_impl& __t) noexcept { return __t; } - constexpr const _Inherited& - _M_tail() const noexcept { return *this; } + static constexpr const _Inherited& + _M_tail(const _Tuple_impl& __t) noexcept { return __t; } constexpr _Tuple_impl() : _Inherited(), _Base() { } @@ -276,17 +276,20 @@ _Tuple_impl(_Tuple_impl&& __in) noexcept(__and_, is_nothrow_move_constructible<_Inherited>>::value) - : _Inherited(std::move(__in._M_tail())), - _Base(std::forward<_Head>(__in._M_head())) { } + : _Inherited(std::move(_M_tail(__in))), + _Base(std::forward<_Head>(_M_head(__in))) { } template constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in) - : _Inherited(__in._M_tail()), _Base(__in._M_head()) { } + : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), + _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { } template _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) - : _Inherited(std::move(__in._M_tail())), - _Base(std::forward<_UHead>(__in._M_head())) { } + : _Inherited(std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), + _Base(std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } template _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) @@ -311,34 +314,38 @@ template _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, const _Tuple_impl& __in) - : _Inherited(__tag, __a, __in._M_tail()), - _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __in._M_head()) { } + : _Inherited(__tag, __a, _M_tail(__in)), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { } template _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, _Tuple_impl&& __in) - : _Inherited(__tag, __a, std::move(__in._M_tail())), + : _Inherited(__tag, __a, std::move(_M_tail(__in))), _Base(__use_alloc<_Head, _Alloc, _Head>(__a), - std::forward<_Head>(__in._M_head())) { } + std::forward<_Head>(_M_head(__in))) { } template _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, const _Tuple_impl<_Idx, _UElements...>& __in) - : _Inherited(__tag, __a, __in._M_tail()), - _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __in._M_head()) { } + : _Inherited(__tag, __a, + _Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), + _Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { } template _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, _Tuple_impl<_Idx, _UHead, _UTails...>&& __in) - : _Inherited(__tag, __a, std::move(__in._M_tail())), + : _Inherited(__tag, __a, std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), - std::forward<_UHead>(__in._M_head())) { } + std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } _Tuple_impl& operator=(const _Tuple_impl& __in) { - _M_head() = __in._M_head(); - _M_tail() = __in._M_tail(); + _M_head(*this) = _M_head(__in); + _M_tail(*this) = _M_tail(__in); return *this; } @@ -347,8 +354,8 @@ noexcept(__and_, is_nothrow_move_assignable<_Inherited>>::value) { - _M_head() = std::forward<_Head>(__in._M_head()); - _M_tail() = std::move(__in._M_tail()); + _M_head(*this) = std::forward<_Head>(_M_head(__in)); + _M_tail(*this) = std::move(_M_tail(__in)); return *this; } @@ -356,8 +363,8 @@ _Tuple_impl& operator=(const _Tuple_impl<_Idx, _UElements...>& __in) { - _M_head() = __in._M_head(); - _M_tail() = __in._M_tail(); + _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in); + _M_tail(*this) = _Tuple_impl<_Idx, _UElements...>::_M_tail(__in); return *this; } @@ -365,8 +372,10 @@ _Tuple_impl& operator=(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) { - _M_head() = std::forward<_UHead>(__in._M_head()); - _M_tail() = std::move(__in._M_tail()); + _M_head(*this) = std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)); + _M_tail(*this) = std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)); return *this; } @@ -375,11 +384,11 @@ _M_swap(_Tuple_impl& __in) noexcept(noexcept(swap(std::declval<_Head&>(), std::declval<_Head&>())) - && noexcept(__in._M_tail()._M_swap(__in._M_tail()))) + && noexcept(_M_tail(__in)._M_swap(_M_tail(__in)))) { using std::swap; - swap(this->_M_head(), __in._M_head()); - _Inherited::_M_swap(__in._M_tail()); + swap(_M_head(*this), _M_head(__in)); + _Inherited::_M_swap(_M_tail(__in)); } }; @@ -656,8 +665,8 @@ tuple& operator=(const pair<_U1, _U2>& __in) { - this->_M_head() = __in.first; - this->_M_tail()._M_head() = __in.second; + this->_M_head(*this) = __in.first; + this->_M_tail(*this)._M_head(*this) = __in.second; return *this; } @@ -665,8 +674,8 @@ tuple& operator=(pair<_U1, _U2>&& __in) { - this->_M_head() = std::forward<_U1>(__in.first); - this->_M_tail()._M_head() = std::forward<_U2>(__in.second); + this->_M_head(*this) = std::forward<_U1>(__in.first); + this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second); return *this; } @@ -747,34 +756,34 @@ : public integral_constant { }; template - inline typename __add_ref<_Head>::type + constexpr typename __add_ref<_Head>::type __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept - { return __t._M_head(); } + { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } template - inline constexpr typename __add_c_ref<_Head>::type + constexpr typename __add_c_ref<_Head>::type __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept - { return __t._M_head(); } + { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } // Return a reference (const reference, rvalue reference) to the ith element // of a tuple. Any const or non-const ref elements are returned with their // original type. template - inline typename __add_ref< + constexpr typename __add_ref< typename tuple_element<__i, tuple<_Elements...>>::type >::type get(tuple<_Elements...>& __t) noexcept { return __get_helper<__i>(__t); } template - inline constexpr typename __add_c_ref< + constexpr typename __add_c_ref< typename tuple_element<__i, tuple<_Elements...>>::type >::type get(const tuple<_Elements...>& __t) noexcept { return __get_helper<__i>(__t); } template - inline typename __add_r_ref< + constexpr typename __add_r_ref< typename tuple_element<__i, tuple<_Elements...>>::type >::type get(tuple<_Elements...>&& __t) noexcept @@ -880,13 +889,13 @@ template struct array; template - _Tp& get(array<_Tp, _Nm>&) noexcept; + constexpr _Tp& get(array<_Tp, _Nm>&) noexcept; template - _Tp&& get(array<_Tp, _Nm>&&) noexcept; + constexpr _Tp&& get(array<_Tp, _Nm>&&) noexcept; template - const _Tp& get(const array<_Tp, _Nm>&) noexcept; + constexpr const _Tp& get(const array<_Tp, _Nm>&) noexcept; template struct __is_tuple_like_impl : false_type @@ -1022,7 +1031,7 @@ struct __tuple_concater<_Ret, std::_Index_tuple<_Is...>, _Tp, _Tpls...> { template - static _Ret + static constexpr _Ret _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us) { typedef typename __make_1st_indices<_Tpls...>::__type __idx; @@ -1037,18 +1046,18 @@ struct __tuple_concater<_Ret, std::_Index_tuple<>> { template - static _Ret + static constexpr _Ret _S_do(_Us&&... __us) { return _Ret(std::forward<_Us>(__us)...); } }; - template - inline typename - std::enable_if<__and_<__is_tuple_like<_Tpls>...>::value, - typename __tuple_cat_result<_Tpls...>::__type>::type + template...>::value>::type> + constexpr auto tuple_cat(_Tpls&&... __tpls) + -> typename __tuple_cat_result<_Tpls...>::__type { typedef typename __tuple_cat_result<_Tpls...>::__type __ret; typedef typename __make_1st_indices<_Tpls...>::__type __idx; Index: include/std/utility =================================================================== --- include/std/utility (revision 178791) +++ include/std/utility (working copy) @@ -105,17 +105,17 @@ struct __pair_get<0> { template - static _Tp1& + static constexpr _Tp1& __get(std::pair<_Tp1, _Tp2>& __pair) noexcept { return __pair.first; } template - static _Tp1&& + static constexpr _Tp1&& __move_get(std::pair<_Tp1, _Tp2>&& __pair) noexcept { return std::forward<_Tp1>(__pair.first); } template - static const _Tp1& + static constexpr const _Tp1& __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept { return __pair.first; } }; @@ -124,33 +124,33 @@ struct __pair_get<1> { template - static _Tp2& + static constexpr _Tp2& __get(std::pair<_Tp1, _Tp2>& __pair) noexcept { return __pair.second; } template - static _Tp2&& + static constexpr _Tp2&& __move_get(std::pair<_Tp1, _Tp2>&& __pair) noexcept { return std::forward<_Tp2>(__pair.second); } template - static const _Tp2& + static constexpr const _Tp2& __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept { return __pair.second; } }; template - inline typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type& + constexpr typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type& get(std::pair<_Tp1, _Tp2>& __in) noexcept { return __pair_get<_Int>::__get(__in); } template - inline typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type&& + constexpr typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type&& get(std::pair<_Tp1, _Tp2>&& __in) noexcept { return __pair_get<_Int>::__move_get(std::move(__in)); } template - inline const typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type& + constexpr const typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type& get(const std::pair<_Tp1, _Tp2>& __in) noexcept { return __pair_get<_Int>::__const_get(__in); } Index: include/std/array =================================================================== --- include/std/array (revision 178791) +++ include/std/array (working copy) @@ -264,19 +264,19 @@ { typedef _Tp type; }; template - inline _Tp& + constexpr _Tp& get(array<_Tp, _Nm>& __arr) noexcept - { return __arr[_Int]; } + { return __arr._M_instance[_Int]; } template - inline _Tp&& + constexpr _Tp&& get(array<_Tp, _Nm>&& __arr) noexcept { return std::move(get<_Int>(__arr)); } template - inline const _Tp& + constexpr const _Tp& get(const array<_Tp, _Nm>& __arr) noexcept - { return __arr[_Int]; } + { return __arr._M_instance[_Int]; } _GLIBCXX_END_NAMESPACE_VERSION } // namespace Index: testsuite/23_containers/array/constexpr_get.cc =================================================================== --- testsuite/23_containers/array/constexpr_get.cc (revision 0) +++ testsuite/23_containers/array/constexpr_get.cc (revision 0) @@ -0,0 +1,30 @@ +// { dg-options "-std=gnu++0x" } +// { dg-do compile } + +// Copyright (C) 2011 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 +// . + +// Tuple + +#include + +std::array ai; +const std::array cai(ai); + +constexpr const int& cri = std::get<0>(cai); +constexpr int& ri = std::get<0>(ai); +constexpr int&& rri = std::get<0>(std::move(ai)); Index: testsuite/20_util/tuple/creation_functions/constexpr.cc =================================================================== --- testsuite/20_util/tuple/creation_functions/constexpr.cc (revision 178791) +++ testsuite/20_util/tuple/creation_functions/constexpr.cc (working copy) @@ -63,7 +63,6 @@ } // tuple_cat -#if 0 void test_tuple_cat() { @@ -74,7 +73,6 @@ constexpr tuple_type2 t2 { 55, 99, 77.77 }; constexpr auto cat1 = std::tuple_cat(t1, t2); } -#endif int main() @@ -84,10 +82,7 @@ #endif test_get(); - -#if 0 test_tuple_cat(); -#endif return 0; } Index: testsuite/20_util/tuple/element_access/constexpr_get.cc =================================================================== --- testsuite/20_util/tuple/element_access/constexpr_get.cc (revision 0) +++ testsuite/20_util/tuple/element_access/constexpr_get.cc (revision 0) @@ -0,0 +1,30 @@ +// { dg-options "-std=gnu++0x" } +// { dg-do compile } + +// Copyright (C) 2011 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 +// . + +// Tuple + +#include + +std::tuple ti; +const std::tuple cti; + +constexpr const int& cri = std::get<0>(cti); +constexpr int& ri = std::get<0>(ti); +constexpr int&& rri = std::get<0>(std::move(ti)); Index: testsuite/20_util/pair/constexpr_get.cc =================================================================== --- testsuite/20_util/pair/constexpr_get.cc (revision 0) +++ testsuite/20_util/pair/constexpr_get.cc (revision 0) @@ -0,0 +1,28 @@ +// { dg-options "-std=gnu++0x" } +// { dg-do compile } + +// Copyright (C) 2011 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 +// . + +#include + +std::pair pi; +const std::pair cpi; + +constexpr const int& cri = std::get<0>(cpi); +constexpr int& ri = std::get<0>(pi); +constexpr int&& rri = std::get<0>(std::move(pi)); Index: testsuite/20_util/weak_ptr/comparison/cmp_neg.cc =================================================================== --- testsuite/20_util/weak_ptr/comparison/cmp_neg.cc (revision 178791) +++ testsuite/20_util/weak_ptr/comparison/cmp_neg.cc (working copy) @@ -51,7 +51,7 @@ // { dg-warning "note" "" { target *-*-* } 485 } // { dg-warning "note" "" { target *-*-* } 479 } // { dg-warning "note" "" { target *-*-* } 468 } -// { dg-warning "note" "" { target *-*-* } 831 } +// { dg-warning "note" "" { target *-*-* } 840 } // { dg-warning "note" "" { target *-*-* } 1056 } // { dg-warning "note" "" { target *-*-* } 1050 } // { dg-warning "note" "" { target *-*-* } 342 }