Hi,

Daniel kindly helped adjusting <tuple> 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  <daniel.krueg...@googlemail.com>
            Paolo Carlini  <paolo.carl...@oracle.com>

        * 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<std::size_t _Idx, typename _Head>
@@ -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<_Head>,
                      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<typename... _UElements>
         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<typename _UHead, typename... _UTails>
         _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<typename _Alloc>
        _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
@@ -311,34 +314,38 @@
       template<typename _Alloc>
         _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<typename _Alloc>
        _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<typename _Alloc, typename... _UElements>
        _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<typename _Alloc, typename _UHead, typename... _UTails>
        _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<_Head>,
                      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<std::size_t, sizeof...(_Elements)> { };
 
   template<std::size_t __i, typename _Head, typename... _Tail>
-    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<std::size_t __i, typename _Head, typename... _Tail>
-    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<std::size_t __i, typename... _Elements>
-    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<std::size_t __i, typename... _Elements>
-    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<std::size_t __i, typename... _Elements>
-    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<typename, std::size_t> struct array;
 
   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
-    _Tp& get(array<_Tp, _Nm>&) noexcept;
+    constexpr _Tp& get(array<_Tp, _Nm>&) noexcept;
 
   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
-    _Tp&& get(array<_Tp, _Nm>&&) noexcept;
+    constexpr _Tp&& get(array<_Tp, _Nm>&&) noexcept;
 
   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
-    const _Tp& get(const array<_Tp, _Nm>&) noexcept;
+    constexpr const _Tp& get(const array<_Tp, _Nm>&) noexcept;
 
   template<typename>
     struct __is_tuple_like_impl : false_type
@@ -1022,7 +1031,7 @@
     struct __tuple_concater<_Ret, std::_Index_tuple<_Is...>, _Tp, _Tpls...>
     {
       template<typename... _Us>
-        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<typename... _Us>
-       static _Ret
+       static constexpr _Ret
        _S_do(_Us&&... __us)
         {
          return _Ret(std::forward<_Us>(__us)...);
        }
     };
 
-  template<typename... _Tpls>
-    inline typename
-    std::enable_if<__and_<__is_tuple_like<_Tpls>...>::value,
-                   typename __tuple_cat_result<_Tpls...>::__type>::type
+  template<typename... _Tpls, typename = typename
+           enable_if<__and_<__is_tuple_like<_Tpls>...>::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<typename _Tp1, typename _Tp2>
-        static _Tp1&
+        static constexpr _Tp1&
         __get(std::pair<_Tp1, _Tp2>& __pair) noexcept
         { return __pair.first; }
 
       template<typename _Tp1, typename _Tp2>
-        static _Tp1&&
+        static constexpr _Tp1&&
         __move_get(std::pair<_Tp1, _Tp2>&& __pair) noexcept
         { return std::forward<_Tp1>(__pair.first); }
 
       template<typename _Tp1, typename _Tp2>
-        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<typename _Tp1, typename _Tp2>
-        static _Tp2&
+        static constexpr _Tp2&
         __get(std::pair<_Tp1, _Tp2>& __pair) noexcept
         { return __pair.second; }
 
       template<typename _Tp1, typename _Tp2>
-        static _Tp2&&
+        static constexpr _Tp2&&
         __move_get(std::pair<_Tp1, _Tp2>&& __pair) noexcept
         { return std::forward<_Tp2>(__pair.second); }
 
       template<typename _Tp1, typename _Tp2>
-        static const _Tp2&
+        static constexpr const _Tp2&
         __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept
         { return __pair.second; }
     };
 
   template<std::size_t _Int, class _Tp1, class _Tp2>
-    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<std::size_t _Int, class _Tp1, class _Tp2>
-    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<std::size_t _Int, class _Tp1, class _Tp2>
-    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<std::size_t _Int, typename _Tp, std::size_t _Nm>
-    inline _Tp&
+    constexpr _Tp&
     get(array<_Tp, _Nm>& __arr) noexcept
-    { return __arr[_Int]; }
+    { return __arr._M_instance[_Int]; }
 
   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
-    inline _Tp&&
+    constexpr _Tp&&
     get(array<_Tp, _Nm>&& __arr) noexcept
     { return std::move(get<_Int>(__arr)); }
 
   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
-    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
+// <http://www.gnu.org/licenses/>.
+
+// Tuple
+
+#include <array>
+
+std::array<int, 5> ai;
+const std::array<int, 5> 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
+// <http://www.gnu.org/licenses/>.
+
+// Tuple
+
+#include <tuple>
+
+std::tuple<int> ti;
+const std::tuple<int> 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
+// <http://www.gnu.org/licenses/>.
+
+#include <utility>
+
+std::pair<int, int> pi;
+const std::pair<int, int> 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 }

Reply via email to