Index: include/tuple =================================================================== --- include/tuple +++ include/tuple @@ -500,6 +500,7 @@ class _LIBCPP_TYPE_VIS_ONLY tuple { typedef __tuple_impl::type, _Tp...> base; + typedef typename tuple_element<0, __tuple_types<_Tp...>>::type _First; base base_; @@ -655,6 +656,8 @@ template , __tuple_types<_First>>::value) && __tuple_convertible<_Tuple, tuple>::value, bool >::type = false @@ -666,6 +669,9 @@ template , __tuple_types<_First>>::value || + __tuple_constructible, __tuple_types<_First>>::value)) && __tuple_constructible<_Tuple, tuple>::value && !__tuple_convertible<_Tuple, tuple>::value, bool @@ -679,6 +685,8 @@ template , __tuple_types<_First>>::value) && __tuple_convertible<_Tuple, tuple>::value >::type > Index: test/std/utilities/tuple/tuple.tuple/tuple.cnstr/tuple_like_sfinae.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/tuple/tuple.tuple/tuple.cnstr/tuple_like_sfinae.pass.cpp @@ -0,0 +1,44 @@ +#include +#include +#include + +#include "tracked_value.h" + +int main() +{ + { + TrackedValue v; + std::tuple t1(v); + // This selects the wrong constructor and constructs std::tuple&& + // from a temporary. + std::tuple&&> t2(std::move(t1)); + // This moves from the reference constructed from the temporary. + std::tuple> t3(std::move(t2)); + } + { + TrackedValue v; + std::tuple t1(v); + std::tuple const &> t2(t1); + std::tuple> t3(t2); + } + { + TrackedValue v; + std::tuple t1(v); + std::tuple &> t2(t1); + std::tuple> t3(t2); + } + { + TrackedValue v; + std::tuple t1(v); + std::tuple&&> t2(std::move(t1)); + std::allocator a; + std::tuple> t3(std::allocator_arg, a, std::move(t2)); + } + { + TrackedValue v; + std::tuple t1(v); + std::tuple const &> t2(t1); + std::allocator a; + std::tuple> t3(std::allocator_arg, a, t2); + } +}