@@ -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<const T></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<T>::value</code> and
+ only use it if valid.
</para></listitem></varlistentry>
</variablelist>
@@ -88,18 +88,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct tuple_size;
// _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 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_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>
- : integral_constant<size_t, tuple_size<_Tp>::value> { };
+ 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>
@@ -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, "" );