Patchwork [v3] define std::integer_sequence et al

login
register
mail settings
Submitter Jonathan Wakely
Date Oct. 31, 2013, 7:41 p.m.
Message ID <CAH6eHdSrY6ghW=jP7+FFbFuLVxgcRrDvjeqaF3R03Ay9HYuWqA@mail.gmail.com>
Download mbox | patch
Permalink /patch/287594/
State New
Headers show

Comments

Jonathan Wakely - Oct. 31, 2013, 7:41 p.m.
Implement my N3658 proposal for C++14.  I moved the existing
_Build_index_tuple from <tuple> to <utility> and re-used it for
std::make_integer_sequence (so that if G++ one day provides an
intrinsic to generate a parameter pack of integers [0, N) we only need
to change one place to use it.)

2013-10-31  Jonathan Wakely  <jwakely.gcc@gmail.com>

        * include/std/tuple (_Index_tuple, _Build_index_tuple): Move to
        <utility>.
        * include/std/utility (integer_sequence, make_integer_sequence,
        index_sequence, make_index_sequence, index_sequence_for): Define.
        * doc/xml/manual/status_cxx2014.xml: Update.
        * testsuite/20_util/integer_sequence/intseq.cc: New.
        * testsuite/20_util/integer_sequence/requirements/typedefs.cc: New.

Tested x86_64-linux, committed to trunk.
commit 29a1079a3edcb51833cf0739affb2d9b3a59d4c3
Author: Jonathan Wakely <jwakely.gcc@gmail.com>
Date:   Sun Apr 28 13:59:42 2013 +0100

    	* include/std/tuple (_Index_tuple, _Build_index_tuple): Move to
    	<utility>.
    	* include/std/utility (integer_sequence, make_integer_sequence,
    	index_sequence, make_index_sequence, index_sequence_for): Define.
    	* doc/xml/manual/status_cxx2014.xml: Update.
    	* testsuite/20_util/integer_sequence/intseq.cc: New.
    	* testsuite/20_util/integer_sequence/requirements/typedefs.cc: New.

Patch

diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2014.xml b/libstdc++-v3/doc/xml/manual/status_cxx2014.xml
index 1f20f0e..4ef4334 100644
--- a/libstdc++-v3/doc/xml/manual/status_cxx2014.xml
+++ b/libstdc++-v3/doc/xml/manual/status_cxx2014.xml
@@ -185,8 +185,8 @@  particular release.
 	</link>
       </entry>
       <entry>Compile-time integer sequences</entry>
-      <entry>WIP</entry>
-      <entry>Need tests</entry>
+      <entry>Y</entry>
+      <entry/>
     </row>
 
     <row>
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 063ce02..2580f78 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -917,27 +917,6 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
             <typename std::remove_reference<_Tp>::type>::type>::type
     { };
 
-  // Stores a tuple of indices.  Also used by bind() to extract the elements
-  // in a tuple. 
-  template<std::size_t... _Indexes>
-    struct _Index_tuple
-    {
-      typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next;
-    };
-
-  // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
-  template<std::size_t _Num>
-    struct _Build_index_tuple
-    {
-      typedef typename _Build_index_tuple<_Num - 1>::__type::__next __type;
-    };
-
-  template<>
-    struct _Build_index_tuple<0>
-    {
-      typedef _Index_tuple<> __type;
-    };
-
   template<std::size_t, typename, typename, std::size_t>
     struct __make_tuple_impl;
 
diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
index ad30ad7..627f79b 100644
--- a/libstdc++-v3/include/std/utility
+++ b/libstdc++-v3/include/std/utility
@@ -194,6 +194,67 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 #endif
 
+  // Stores a tuple of indices.  Used by tuple and pair, and by bind() to
+  // extract the elements in a tuple.
+  template<size_t... _Indexes>
+    struct _Index_tuple
+    {
+      typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next;
+    };
+
+  // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
+  template<size_t _Num>
+    struct _Build_index_tuple
+    {
+      typedef typename _Build_index_tuple<_Num - 1>::__type::__next __type;
+    };
+
+  template<>
+    struct _Build_index_tuple<0>
+    {
+      typedef _Index_tuple<> __type;
+    };
+
+#if __cplusplus > 201103L
+  /// Class template integer_sequence
+  template<typename _Tp, _Tp... _Idx>
+    struct integer_sequence
+    {
+      typedef _Tp value_type;
+      static constexpr size_t size() { return sizeof...(_Idx); }
+    };
+
+  template<typename _Tp, _Tp _Num,
+	   typename _ISeq = typename _Build_index_tuple<_Num>::__type>
+    struct _Make_integer_sequence;
+
+  template<typename _Tp, _Tp _Num,  size_t... _Idx>
+    struct _Make_integer_sequence<_Tp, _Num, _Index_tuple<_Idx...>>
+    {
+      static_assert( _Num >= 0,
+		     "Cannot make integer sequence of negative length" );
+
+      typedef integer_sequence<_Tp, static_cast<_Tp>(_Idx)...> __type;
+    };
+
+  /// Alias template make_integer_sequence
+  template<typename _Tp, _Tp _Num>
+    using make_integer_sequence
+      = typename _Make_integer_sequence<_Tp, _Num>::__type;
+
+  /// Alias template index_sequence
+  template<size_t... _Idx>
+    using index_sequence = integer_sequence<size_t, _Idx...>;
+
+  /// Alias template make_index_sequence
+  template<size_t _Num>
+    using make_index_sequence = make_integer_sequence<size_t, _Num>;
+
+  /// Alias template index_sequence_for
+  template<typename... _Types>
+    using index_sequence_for = make_index_sequence<sizeof...(_Types)>;
+#endif
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
diff --git a/libstdc++-v3/testsuite/20_util/integer_sequence/intseq.cc b/libstdc++-v3/testsuite/20_util/integer_sequence/intseq.cc
new file mode 100644
index 0000000..0f3ed41
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/integer_sequence/intseq.cc
@@ -0,0 +1,27 @@ 
+// { 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/>.
+
+#include <type_traits>
+#include <utility>
+
+using std::integer_sequence;
+
+static_assert( integer_sequence<int>::size() == 0, "size() == 0" );
+static_assert( integer_sequence<int, 0, 1, 2>::size() == 3, "size() == 3" );
diff --git a/libstdc++-v3/testsuite/20_util/integer_sequence/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/integer_sequence/requirements/typedefs.cc
new file mode 100644
index 0000000..ab26800
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/integer_sequence/requirements/typedefs.cc
@@ -0,0 +1,62 @@ 
+// { 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/>.
+
+#include <utility>
+#include <type_traits>
+
+using std::is_same;
+using std::integer_sequence;
+using std::make_integer_sequence;
+using std::index_sequence;
+using std::make_index_sequence;
+using std::index_sequence_for;
+
+static_assert( is_same<integer_sequence<int>::value_type, int>::value,
+	       "int value_type");
+
+static_assert( is_same<integer_sequence<short>::value_type, short>::value,
+	       "short value_type");
+
+static_assert( is_same<make_integer_sequence<int, 0>,
+		       integer_sequence<int>>::value,
+	       "make empty int seq" );
+
+static_assert( is_same<make_integer_sequence<int, 2>,
+		       integer_sequence<int, 0, 1>>::value,
+	       "make non-empty int seq" );
+
+static_assert( is_same<make_integer_sequence<unsigned, 0>,
+		       integer_sequence<unsigned>>::value,
+	       "make empty unsigned seq" );
+
+static_assert( is_same<make_integer_sequence<unsigned, 2>,
+		       integer_sequence<unsigned, 0, 1>>::value,
+	       "make non-empty unsigned seq" );
+
+static_assert( is_same<index_sequence<0, 1>,
+		       integer_sequence<std::size_t, 0, 1>>::value,
+	       "index seq" );
+
+static_assert( is_same<make_index_sequence<2>, index_sequence<0, 1>>::value,
+	       "make index seq" );
+
+static_assert( is_same<index_sequence_for<char, int, void, double>,
+		       index_sequence<0, 1, 2, 3>>::value,
+	       "index_sequence_for" );