Make std::tuple_size<cv T> SFINAE-friendly (LWG 2770)
authorJonathan Wakely <jwakely@redhat.com>
Tue, 15 Nov 2016 19:32:44 +0000 (19:32 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 15 Nov 2016 19:32:44 +0000 (19:32 +0000)
* doc/xml/manual/intro.xml: Document LWG 2770 status. Remove entries
for 2742 and 2748.
* doc/html/*: Regenerate.
* include/std/utility (__tuple_size_cv_impl): New helper to safely
detect tuple_size<T>::value, as per LWG 2770.
(tuple_size<cv T>): Adjust partial specializations to derive from
__tuple_size_cv_impl.
* testsuite/20_util/tuple/cv_tuple_size.cc: Test SFINAE-friendliness.

From-SVN: r242452

libstdc++-v3/ChangeLog
libstdc++-v3/doc/html/manual/bugs.html
libstdc++-v3/doc/xml/manual/intro.xml
libstdc++-v3/include/std/utility
libstdc++-v3/testsuite/20_util/tuple/cv_tuple_size.cc

index 77669da173fd1cf04e3ec7dff1f1200d3bd01437..6bf1ecbcf0e2ffd4fb6eede81e024420e8550785 100644 (file)
@@ -1,5 +1,14 @@
 2016-11-15  Jonathan Wakely  <jwakely@redhat.com>
 
+       * doc/xml/manual/intro.xml: Document LWG 2770 status. Remove entries
+       for 2742 and 2748.
+       * doc/html/*: Regenerate.
+       * include/std/utility (__tuple_size_cv_impl): New helper to safely
+       detect tuple_size<T>::value, as per LWG 2770.
+       (tuple_size<cv T>): Adjust partial specializations to derive from
+       __tuple_size_cv_impl.
+       * testsuite/20_util/tuple/cv_tuple_size.cc: Test SFINAE-friendliness.
+
        * testsuite/libstdc++-prettyprinters/cxx17.cc: Adjust test for
        variant<T&>.
 
index d4a39d82e896196a770349a120e6c161e99ddac2..ee39a954c5c8fb6779c597543cccd2361b64097e 100644 (file)
        <span class="emphasis"><em><code class="code">priority_queue</code> lacking comparator typedef
        </em></span>
     </span></dt><dd><p>Define the <code class="code">value_compare</code> typedef.
-    </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2742" target="_top">2742</a>:
-       <span class="emphasis"><em>Inconsistent <code class="code">string</code> interface taking <code class="code">string_view</code>
+    </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2770" target="_top">2770</a>:
+       <span class="emphasis"><em><code class="code">tuple_size&lt;const T&gt;</code> specialization is not
+        SFINAE compatible and breaks decomposition declarations
        </em></span>
-    </span></dt><dd><p>Add the new constructor and additionally constrain it
-      to avoid ambiguities with non-const <code class="code">charT*</code>.
-    </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2748" target="_top">2748</a>:
-       <span class="emphasis"><em>swappable traits for optionals
-       </em></span>
-    </span></dt><dd><p>Disable the non-member <code class="code">swap</code> overload when
-      the contained object is not swappable.
+    </span></dt><dd><p>Safely detect <code class="code">tuple_size&lt;T&gt;::value</code> and
+      only use it if valid.
     </p></dd></dl></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="license.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="status.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="setup.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">License </td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 2. Setup</td></tr></table></div></body></html>
\ No newline at end of file
index 7f2586d816045881ca99cdba0a2c9823f36950eb..d23008ad332dd29f136e41ac79983bfab532fe4c 100644 (file)
@@ -1107,20 +1107,13 @@ requirements of the license of GCC.
     <listitem><para>Define the <code>value_compare</code> typedef.
     </para></listitem></varlistentry>
 
-    <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2742">2742</link>:
-       <emphasis>Inconsistent <code>string</code> interface taking <code>string_view</code>
+    <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2770">2770</link>:
+       <emphasis><code>tuple_size&lt;const T&gt;</code> specialization is not
+        SFINAE compatible and breaks decomposition declarations
        </emphasis>
     </term>
-    <listitem><para>Add the new constructor and additionally constrain it
-      to avoid ambiguities with non-const <code>charT*</code>.
-    </para></listitem></varlistentry>
-
-    <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2748">2748</link>:
-       <emphasis>swappable traits for optionals
-       </emphasis>
-    </term>
-    <listitem><para>Disable the non-member <code>swap</code> overload when
-      the contained object is not swappable.
+    <listitem><para>Safely detect <code>tuple_size&lt;T&gt;::value</code> and
+      only use it if valid.
     </para></listitem></varlistentry>
 
   </variablelist>
index 2ca52fe699ae10f271a693667c5e76028c074c2a..3982156d6951520ba2db6c0c7f28aa573e9f633b 100644 (file)
@@ -88,18 +88,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct tuple_size;
 
   // _GLIBCXX_RESOLVE_LIB_DEFECTS
-  // 2313. tuple_size should always derive from integral_constant<size_t, N>
+  // 2770. tuple_size<const T> specialization is not SFINAE compatible
+  template<typename _Tp, typename = void>
+    struct __tuple_size_cv_impl { };
+
   template<typename _Tp>
-    struct tuple_size<const _Tp>
+    struct __tuple_size_cv_impl<_Tp, __void_t<decltype(tuple_size<_Tp>::value)>>
     : integral_constant<size_t, tuple_size<_Tp>::value> { };
 
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2313. tuple_size should always derive from integral_constant<size_t, N>
+  template<typename _Tp>
+    struct tuple_size<const _Tp> : __tuple_size_cv_impl<_Tp> { };
+
   template<typename _Tp>
-    struct tuple_size<volatile _Tp>
-    : integral_constant<size_t, tuple_size<_Tp>::value> { };
+    struct tuple_size<volatile _Tp> : __tuple_size_cv_impl<_Tp> { };
 
   template<typename _Tp>
-    struct tuple_size<const volatile _Tp>
-    : integral_constant<size_t, tuple_size<_Tp>::value> { };
+    struct tuple_size<const volatile _Tp> : __tuple_size_cv_impl<_Tp> { };
 
   /// Gives the type of the ith element of a given tuple type.
   template<std::size_t __i, typename _Tp>
index df5e0e993d361aa0e7e233b62dfd632e9ab30611..c4a1e02db87a913affa596e27d6062cb93b6f5f9 100644 (file)
@@ -42,3 +42,13 @@ int main()
   test01();
   return 0;
 }
+
+// LWG DR 2770. tuple_size<const T> specialization is not SFINAE compatible
+template<typename T, typename = void>
+struct has_value : std::false_type { };
+
+template<typename T>
+struct has_value<T, std::__void_t<decltype(T::value)>> : std::true_type { };
+
+static_assert( !has_value<std::tuple_size<int>>::value, "" );
+static_assert( !has_value<std::tuple_size<const int>>::value, "" );