From 0527c6207af5de565bbd77e64f953bbc785cee8d Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Sun, 1 Apr 2012 23:10:42 +0000 Subject: [PATCH] I believe tuple is still under development in the standard. Daniel Krugler is/will be making convincing arguments that a modified form of LWG 2051 (currently NAD Future) is easily acheivable and desirable. He has demonstrated that a tuple where all of the T are implicitly convertible from U... should have a tuple constructor that is also implicit, instead of explicit. This would support the use cases in LWG 2051 while not undermining T... with explicit conversions from U.... This check-in is an experimental implementation of Daniel's work. I believe this work to be mature enough to warrant inclusion into libc++. If anyone sees real-world problems that this check in causes, please let me know and I will revert it, and provide the feedback to the LWG. llvm-svn: 153855 --- libcxx/include/__tuple | 29 +++++++++- libcxx/include/tuple | 58 +++++++++++++++++-- .../tuple.tuple/tuple.cnstr/UTypes.fail.cpp | 26 ++++++++- .../tuple.cnstr/const_Types.fail.cpp | 3 +- 4 files changed, 105 insertions(+), 11 deletions(-) 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; } }