diff --git a/libcxx/include/__tuple b/libcxx/include/__tuple index 3b2be1c5a74d..82168048e6ce 100644 --- a/libcxx/include/__tuple +++ b/libcxx/include/__tuple @@ -216,7 +216,7 @@ struct __tuple_convertible_imp : public false_type {}; template struct __tuple_convertible_imp, __tuple_types<_Up0, _Up...> > : public integral_constant::value && + is_convertible<_Tp0, _Up0>::value && __tuple_convertible_imp, __tuple_types<_Up...> >::value> {}; template <> @@ -235,6 +235,33 @@ struct __tuple_convertible<_Tp, _Up, true, true> typename __make_tuple_types<_Tp>::type, typename __make_tuple_types<_Up>::type> {}; +// __tuple_constructible + +template +struct __tuple_constructible_imp : public false_type {}; + +template +struct __tuple_constructible_imp, __tuple_types<_Up0, _Up...> > + : public integral_constant::value && + __tuple_constructible_imp, __tuple_types<_Up...> >::value> {}; + +template <> +struct __tuple_constructible_imp, __tuple_types<> > + : public true_type {}; + +template ::type>::value, + bool = __tuple_like<_Up>::value> +struct __tuple_constructible + : public false_type {}; + +template +struct __tuple_constructible<_Tp, _Up, true, true> + : public __tuple_constructible_imp::type>::value == + tuple_size<_Up>::value, + typename __make_tuple_types<_Tp>::type, typename __make_tuple_types<_Up>::type> +{}; + // __tuple_assignable template diff --git a/libcxx/include/tuple b/libcxx/include/tuple index 2bdb05fbc091..683c9dd5294c 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -552,7 +552,7 @@ public: ) {} template ::type - >::value - >::type + >::value, + bool + >::type = false + > + _LIBCPP_INLINE_VISIBILITY + tuple(_Up&&... __u) + : base_(typename __make_tuple_indices::type(), + typename __make_tuple_types::type(), + typename __make_tuple_indices::type(), + typename __make_tuple_types::type(), + _VSTD::forward<_Up>(__u)...) {} + + template , + typename __make_tuple_types::type + >::value && + !__tuple_convertible + < + tuple<_Up...>, + typename __make_tuple_types::type + >::value, + bool + >::type =false > _LIBCPP_INLINE_VISIBILITY explicit @@ -598,15 +630,29 @@ public: _VSTD::forward<_Up>(__u)...) {} template ::value - >::type + __tuple_convertible<_Tuple, tuple>::value, + bool + >::type = false > _LIBCPP_INLINE_VISIBILITY tuple(_Tuple&& __t) : base_(_VSTD::forward<_Tuple>(__t)) {} + template ::value && + !__tuple_convertible<_Tuple, tuple>::value, + bool + >::type = false + > + _LIBCPP_INLINE_VISIBILITY + explicit + tuple(_Tuple&& __t) + : base_(_VSTD::forward<_Tuple>(__t)) {} + template // explicit tuple(UTypes&&... u); +/* + This is testing an extension whereby only Types having an explicit conversion + from UTypes are bound by the explicit tuple constructor. +*/ + #include #include -#include "../MoveOnly.h" +class MoveOnly +{ + MoveOnly(const MoveOnly&); + MoveOnly& operator=(const MoveOnly&); + + int data_; +public: + explicit MoveOnly(int data = 1) : data_(data) {} + MoveOnly(MoveOnly&& x) + : data_(x.data_) {x.data_ = 0;} + MoveOnly& operator=(MoveOnly&& x) + {data_ = x.data_; x.data_ = 0; return *this;} + + int get() const {return data_;} + + bool operator==(const MoveOnly& x) const {return data_ == x.data_;} + bool operator< (const MoveOnly& x) const {return data_ < x.data_;} +}; int main() { { - std::tuple t = MoveOnly(0); + std::tuple t = 1; } } diff --git a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.fail.cpp b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.fail.cpp index d1a03749fd06..e8a78d1983ec 100644 --- a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.fail.cpp +++ b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.fail.cpp @@ -20,7 +20,6 @@ int main() { { - std::tuple t = 2; - assert(std::get<0>(t) == 2); + std::tuple t = 0; } }