diff mbox

Implement N3670, std::get<T> for tuples and pairs

Message ID CAH6eHdSD1gQDFOMtQ9iqTw3_b+hiZ3+LpK3uzUAU5Tidyc5uuA@mail.gmail.com
State New
Headers show

Commit Message

Jonathan Wakely May 19, 2013, 1:31 p.m. UTC
* include/std/tuple (get): Implement N3670.
        * include/std/utility (get): Likewise.
        * testsuite/20_util/pair/get.cc: Move to ...
        * testsuite/20_util/pair/astuple/get.cc: Here.
        * testsuite/20_util/pair/astuple/astuple.cc: New.
        * testsuite/20_util/pair/astuple/constexpr_get.cc: New.
        * testsuite/20_util/pair/astuple/constexpr_get_by_type.cc: New.
        * testsuite/20_util/pair/astuple/get_by_type.cc: New.
        * testsuite/20_util/pair/astuple/get_by_type_neg.cc: New.
        * testsuite/20_util/pair/astuple/get_neg.cc: New.
        * testsuite/20_util/tuple/element_access/constexpr_get_by_type.cc: New.
        * testsuite/20_util/tuple/element_access/get2_by_type.cc: New.
        * testsuite/20_util/tuple/element_access/get_by_type.cc: New.

Tested x86_64-linux, committed to trunk.
commit 336fca0d178e8717f5cb9de45ce26d1cf70e3b06
Author: Jonathan Wakely <jwakely.gcc@gmail.com>
Date:   Sun May 19 13:54:45 2013 +0100

    	* include/std/tuple (get): Implement N3670.
    	* include/std/utility (get): Likewise.
    	* testsuite/20_util/pair/get.cc: Move to ...
    	* testsuite/20_util/pair/astuple/get.cc: Here.
    	* testsuite/20_util/pair/astuple/astuple.cc: New.
    	* testsuite/20_util/pair/astuple/constexpr_get.cc: New.
    	* testsuite/20_util/pair/astuple/constexpr_get_by_type.cc: New.
    	* testsuite/20_util/pair/astuple/get_by_type.cc: New.
    	* testsuite/20_util/pair/astuple/get_by_type_neg.cc: New.
    	* testsuite/20_util/pair/astuple/get_neg.cc: New.
    	* testsuite/20_util/tuple/element_access/constexpr_get_by_type.cc: New.
    	* testsuite/20_util/tuple/element_access/get2_by_type.cc: New.
    	* testsuite/20_util/tuple/element_access/get_by_type.cc: New.
diff mbox

Patch

diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index ee2b2e1..69f5bd1 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -772,6 +772,33 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { return std::forward<typename tuple_element<__i,
 	tuple<_Elements...>>::type&&>(get<__i>(__t)); }
 
+#if __cplusplus > 201103L
+  template<typename _Head, size_t __i, typename... _Tail>
+    constexpr typename __add_ref<_Head>::type
+    __get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
+    { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
+
+  template<typename _Head, size_t __i, typename... _Tail>
+    constexpr typename __add_c_ref<_Head>::type
+    __get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
+    { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
+
+  template <typename _Tp, typename... _Types>
+    constexpr _Tp&
+    get(tuple<_Types...>& __t) noexcept
+    { return __get_helper2<_Tp>(__t); }
+
+  template <typename _Tp, typename... _Types>
+    constexpr _Tp&&
+    get(tuple<_Types...>&& __t) noexcept
+    { return std::move(__get_helper2<_Tp>(__t)); }
+
+  template <typename _Tp, typename... _Types>
+    constexpr const _Tp&
+    get(const tuple<_Types...>& __t) noexcept
+    { return __get_helper2<_Tp>(__t); }
+#endif
+
   // This class helps construct the various comparison operations on tuples
   template<std::size_t __check_equal_size, std::size_t __i, std::size_t __j,
 	   typename _Tp, typename _Up>
diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
index ee8c6b1..ad30ad7 100644
--- a/libstdc++-v3/include/std/utility
+++ b/libstdc++-v3/include/std/utility
@@ -153,8 +153,38 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { return __pair_get<_Int>::__const_get(__in); }
 
 #if __cplusplus > 201103L
+  template <typename _Tp, typename _Up>
+    constexpr _Tp&
+    get(pair<_Tp, _Up>& __p) noexcept
+    { return __p.first; }
+
+  template <typename _Tp, typename _Up>
+    constexpr const _Tp&
+    get(const pair<_Tp, _Up>& __p) noexcept
+    { return __p.first; }
+
+  template <typename _Tp, typename _Up>
+    constexpr _Tp&&
+    get(pair<_Tp, _Up>&& __p) noexcept
+    { return std::move(__p.first); }
+
+  template <typename _Tp, typename _Up>
+    constexpr _Tp&
+    get(pair<_Up, _Tp>& __p) noexcept
+    { return __p.second; }
+
+  template <typename _Tp, typename _Up>
+    constexpr const _Tp&
+    get(const pair<_Up, _Tp>& __p) noexcept
+    { return __p.second; }
+
+  template <typename _Tp, typename _Up>
+    constexpr _Tp&&
+    get(pair<_Up, _Tp>&& __p) noexcept
+    { return std::move(__p.second); }
+
   /// Assign @p __new_val to @p __obj and return its previous value.
-  template <class _Tp, class _Up = _Tp>
+  template <typename _Tp, typename _Up = _Tp>
     inline _Tp
     exchange(_Tp& __obj, _Up&& __new_val)
     {
diff --git a/libstdc++-v3/testsuite/20_util/pair/astuple/astuple.cc b/libstdc++-v3/testsuite/20_util/pair/astuple/astuple.cc
new file mode 100644
index 0000000..32c22b8
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/astuple/astuple.cc
@@ -0,0 +1,37 @@ 
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2013 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>
+#include <type_traits>
+
+typedef std::pair<int, long> test_type;
+
+static_assert( std::tuple_size<test_type>::value == 2, "size is 2" );
+
+template<std::size_t N, typename T>
+  using Tuple_elt = typename std::tuple_element<N, T>::type;
+
+using std::is_same;
+
+static_assert( is_same<Tuple_elt<0, test_type>, test_type::first_type>::value,
+               "first type is int" );
+
+static_assert( is_same<Tuple_elt<1, test_type>, test_type::second_type>::value,
+               "second type is long" );
diff --git a/libstdc++-v3/testsuite/20_util/pair/astuple/constexpr_get.cc b/libstdc++-v3/testsuite/20_util/pair/astuple/constexpr_get.cc
new file mode 100644
index 0000000..d01dcc5
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/astuple/constexpr_get.cc
@@ -0,0 +1,34 @@ 
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 2013 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-like access to pair
+
+#include <utility>
+
+std::pair<int, char> p;
+const std::pair<int, char> cp;
+
+constexpr const int& cri = std::get<0>(cp);
+constexpr int&  ri = std::get<0>(p);
+constexpr int&& rri = std::get<0>(std::move(p));
+
+constexpr const char& crc = std::get<1>(cp);
+constexpr char&  rc = std::get<1>(p);
+constexpr char&& rrc = std::get<1>(std::move(p));
diff --git a/libstdc++-v3/testsuite/20_util/pair/astuple/constexpr_get_by_type.cc b/libstdc++-v3/testsuite/20_util/pair/astuple/constexpr_get_by_type.cc
new file mode 100644
index 0000000..1b18dab
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/astuple/constexpr_get_by_type.cc
@@ -0,0 +1,34 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 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-like access to pair
+
+#include <utility>
+
+std::pair<int, char> p;
+const std::pair<int, char> cp;
+
+constexpr const int& cri = std::get<int>(cp);
+constexpr int&  ri = std::get<int>(p);
+constexpr int&& rri = std::get<int>(std::move(p));
+
+constexpr const char& crc = std::get<char>(cp);
+constexpr char&  rc = std::get<char>(p);
+constexpr char&& rrc = std::get<char>(std::move(p));
diff --git a/libstdc++-v3/testsuite/20_util/pair/astuple/get.cc b/libstdc++-v3/testsuite/20_util/pair/astuple/get.cc
new file mode 100644
index 0000000..0ff807a
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/astuple/get.cc
@@ -0,0 +1,31 @@ 
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+// 2011-05-16  Paolo Carlini  <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2011-2013 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>
+
+void test01()
+{
+  std::pair<float, int> p;
+
+  float&& pfirst __attribute__((unused)) = std::get<0>(std::move(p));
+  int&&  psecond __attribute__((unused)) = std::get<1>(std::move(p));
+}
diff --git a/libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type.cc b/libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type.cc
new file mode 100644
index 0000000..dd26d2d
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type.cc
@@ -0,0 +1,29 @@ 
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2013 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>
+
+void test01()
+{
+  std::pair<float, int> p;
+
+  float&& pfirst __attribute__((unused)) = std::get<float>(std::move(p));
+  int&&  psecond __attribute__((unused)) = std::get<int>(std::move(p));
+}
diff --git a/libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type_neg.cc b/libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type_neg.cc
new file mode 100644
index 0000000..4f7f414
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type_neg.cc
@@ -0,0 +1,28 @@ 
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2013 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>
+
+void test01()
+{
+  std::pair<int, int> p;
+
+  std::get<int>(p);  // { dg-error "ambiguous" }
+}
diff --git a/libstdc++-v3/testsuite/20_util/pair/astuple/get_neg.cc b/libstdc++-v3/testsuite/20_util/pair/astuple/get_neg.cc
new file mode 100644
index 0000000..95fe457
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/astuple/get_neg.cc
@@ -0,0 +1,30 @@ 
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2013 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>
+
+void test01()
+{
+  std::pair<int, int> p;
+
+  std::get<2>(p);  // { dg-error "no matching function" }
+}
+
+// { dg-prune-output "tuple_element<2" }
diff --git a/libstdc++-v3/testsuite/20_util/pair/get.cc b/libstdc++-v3/testsuite/20_util/pair/get.cc
deleted file mode 100644
index 0ff807a..0000000
--- a/libstdc++-v3/testsuite/20_util/pair/get.cc
+++ /dev/null
@@ -1,31 +0,0 @@ 
-// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
-
-// 2011-05-16  Paolo Carlini  <paolo.carlini@oracle.com>
-//
-// Copyright (C) 2011-2013 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>
-
-void test01()
-{
-  std::pair<float, int> p;
-
-  float&& pfirst __attribute__((unused)) = std::get<0>(std::move(p));
-  int&&  psecond __attribute__((unused)) = std::get<1>(std::move(p));
-}
diff --git a/libstdc++-v3/testsuite/20_util/tuple/element_access/constexpr_get_by_type.cc b/libstdc++-v3/testsuite/20_util/tuple/element_access/constexpr_get_by_type.cc
new file mode 100644
index 0000000..9d0239a
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/tuple/element_access/constexpr_get_by_type.cc
@@ -0,0 +1,30 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 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<long, int, const int, long> ti;
+const std::tuple<long, int, const int, long> cti;
+
+constexpr const int& cri = std::get<int>(cti);
+constexpr int&  ri = std::get<int>(ti);
+constexpr int&& rri = std::get<int>(std::move(ti));
diff --git a/libstdc++-v3/testsuite/20_util/tuple/element_access/get2_by_type.cc b/libstdc++-v3/testsuite/20_util/tuple/element_access/get2_by_type.cc
new file mode 100644
index 0000000..dbe5f54
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/tuple/element_access/get2_by_type.cc
@@ -0,0 +1,39 @@ 
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2013 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 <tuple>
+
+void test01()
+{
+  std::tuple<int> t1;
+
+  int&&   t1one __attribute__((unused)) = std::get<int>(std::move(t1));
+
+  std::tuple<float, int> t2;
+
+  float&& t2one __attribute__((unused)) = std::get<0>(std::move(t2));
+  int&&   t2two __attribute__((unused)) = std::get<int>(std::move(t2));
+
+  std::tuple<short, int, double> t3;
+
+  short&&  t3one __attribute__((unused)) = std::get<short>(std::move(t3));
+  int&&    t3two __attribute__((unused)) = std::get<int>(std::move(t3));
+  double&& t3thr __attribute__((unused)) = std::get<double>(std::move(t3));
+}
diff --git a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_by_type.cc b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_by_type.cc
new file mode 100644
index 0000000..5bd15d9
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_by_type.cc
@@ -0,0 +1,44 @@ 
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2013 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>
+#include <testsuite_hooks.h>
+
+using namespace std;
+
+int
+main()
+{
+  bool test __attribute__((unused)) = true;
+
+  int j=1;
+  const int k=2;
+  tuple<int,int &,const int&> a(0,j,k);
+  const tuple<int,int &,const int&> b(1,j,k);
+  VERIFY(get<int>(a)==0 && get<int&>(a)==1 && get<const int&>(a)==2);
+  get<0>(a)=3;
+  get<1>(a)=4;
+  VERIFY(get<int>(a)==3 && get<int&>(a)==4);
+  VERIFY(j==4);
+  get<1>(b)=5;
+  VERIFY(get<int>(b)==1 && get<int&>(b)==5 && get<const int&>(b)==2);
+  VERIFY(j==5);
+}