[libcxx-commits] [libcxx] r365973 - Fix non-conformance it `std::tuple`.
Eric Fiselier via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Jul 12 16:01:48 PDT 2019
Author: ericwf
Date: Fri Jul 12 16:01:48 2019
New Revision: 365973
URL: http://llvm.org/viewvc/llvm-project?rev=365973&view=rev
Log:
Fix non-conformance it `std::tuple`.
Previously we implemented all one trillion tuple-like constructors using
a single generic overload. This worked fairly well, except that it
differed in behavior from the standard version because it didn't
consider both T&& and T const&. This was observable for certain
types.
This patch addresses that issue by splitting the generic constructor
in two. We now provide both T&& and T const& versions of the
tuple-like constructors (sort of).
Modified:
libcxx/trunk/include/tuple
libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp
Modified: libcxx/trunk/include/tuple
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/tuple?rev=365973&r1=365972&r2=365973&view=diff
==============================================================================
--- libcxx/trunk/include/tuple (original)
+++ libcxx/trunk/include/tuple Fri Jul 12 16:01:48 2019
@@ -601,6 +601,25 @@ class _LIBCPP_TEMPLATE_VIS tuple
}
};
+ template <class _Tuple, bool _DisableIfLValue>
+ using _EnableImplicitTupleLikeConstructor = _EnableIf<
+ _CheckTupleLikeConstructor<
+ __tuple_like_with_size<_Tuple, sizeof...(_Tp)>::value
+ && !_PackExpandsToThisTuple<_Tuple>::value
+ && (!is_lvalue_reference<_Tuple>::value || !_DisableIfLValue)
+ >::template __enable_implicit<_Tuple>(),
+ bool
+ >;
+
+ template <class _Tuple, bool _DisableIfLValue>
+ using _EnableExplicitTupleLikeConstructor = _EnableIf<
+ _CheckTupleLikeConstructor<
+ __tuple_like_with_size<_Tuple, sizeof...(_Tp)>::value
+ && !_PackExpandsToThisTuple<_Tuple>::value
+ && (!is_lvalue_reference<_Tuple>::value || !_DisableIfLValue)
+ >::template __enable_explicit<_Tuple>(),
+ bool
+ >;
template <size_t _Jp, class ..._Up> friend _LIBCPP_CONSTEXPR_AFTER_CXX11
typename tuple_element<_Jp, tuple<_Up...> >::type& get(tuple<_Up...>&) _NOEXCEPT;
template <size_t _Jp, class ..._Up> friend _LIBCPP_CONSTEXPR_AFTER_CXX11
@@ -815,35 +834,27 @@ public:
typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(),
_VSTD::forward<_Up>(__u)...) {}
- template <class _Tuple,
- typename enable_if
- <
- _CheckTupleLikeConstructor<
- __tuple_like_with_size<_Tuple, sizeof...(_Tp)>::value
- && !_PackExpandsToThisTuple<_Tuple>::value
- >::template __enable_implicit<_Tuple>(),
- bool
- >::type = false
- >
+ template <class _Tuple, _EnableImplicitTupleLikeConstructor<_Tuple, true> = false>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
tuple(_Tuple&& __t) _NOEXCEPT_((is_nothrow_constructible<_BaseT, _Tuple>::value))
: __base_(_VSTD::forward<_Tuple>(__t)) {}
- template <class _Tuple,
- typename enable_if
- <
- _CheckTupleLikeConstructor<
- __tuple_like_with_size<_Tuple, sizeof...(_Tp)>::value
- && !_PackExpandsToThisTuple<_Tuple>::value
- >::template __enable_explicit<_Tuple>(),
- bool
- >::type = false
- >
+ template <class _Tuple, _EnableImplicitTupleLikeConstructor<const _Tuple&, false> = false>
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+ tuple(const _Tuple& __t) _NOEXCEPT_((is_nothrow_constructible<_BaseT, const _Tuple&>::value))
+ : __base_(__t) {}
+ template <class _Tuple, _EnableExplicitTupleLikeConstructor<_Tuple, true> = false>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
explicit
tuple(_Tuple&& __t) _NOEXCEPT_((is_nothrow_constructible<_BaseT, _Tuple>::value))
: __base_(_VSTD::forward<_Tuple>(__t)) {}
+ template <class _Tuple, _EnableExplicitTupleLikeConstructor<const _Tuple&, false> = false>
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+ explicit
+ tuple(const _Tuple& __t) _NOEXCEPT_((is_nothrow_constructible<_BaseT, const _Tuple&>::value))
+ : __base_(__t) {}
+
template <class _Alloc, class _Tuple,
typename enable_if
<
Modified: libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp?rev=365973&r1=365972&r2=365973&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp Fri Jul 12 16:01:48 2019
@@ -31,6 +31,15 @@ struct Implicit {
Implicit(int x) : value(x) {}
};
+struct ExplicitTwo {
+ ExplicitTwo() {}
+ ExplicitTwo(ExplicitTwo const&) {}
+ ExplicitTwo(ExplicitTwo &&) {}
+
+ template <class T, class = typename std::enable_if<!std::is_same<T, ExplicitTwo>::value>::type>
+ explicit ExplicitTwo(T) {}
+};
+
struct B
{
int id_;
@@ -136,6 +145,13 @@ int main(int, char**)
std::tuple<Implicit> t2 = t1;
assert(std::get<0>(t2).value == 42);
}
+ {
+ static_assert(std::is_convertible<ExplicitTwo&&, ExplicitTwo>::value, "");
+ static_assert(std::is_convertible<std::tuple<ExplicitTwo&&>&&, const std::tuple<ExplicitTwo>&>::value, "");
+ ExplicitTwo e;
+ std::tuple<ExplicitTwo> t = std::tuple<ExplicitTwo&&>(std::move(e));
+ ((void)t);
+ }
return 0;
}
More information about the libcxx-commits
mailing list