Fix tuple's conditionally explicit constructors for very weird user
types.
It seems some people like to write types that can explicitly convert
to anything, but cannot be used to explicitly construct anything.
This patch makes tuple tolerate such types, as is required
by the standard.
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@365074 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/tuple b/include/tuple
index c192d10..de30e86 100644
--- a/include/tuple
+++ b/include/tuple
@@ -521,6 +521,13 @@
template <class ..._Args>
static constexpr bool __enable_implicit() {
return
+ __tuple_constructible<
+ tuple<_Args...>,
+ typename __make_tuple_types<tuple,
+ sizeof...(_Args) < sizeof...(_Tp) ?
+ sizeof...(_Args) :
+ sizeof...(_Tp)>::type
+ >::value &&
__tuple_convertible<
tuple<_Args...>,
typename __make_tuple_types<tuple,
@@ -547,7 +554,8 @@
{
template <class _Tuple>
static constexpr bool __enable_implicit() {
- return __tuple_convertible<_Tuple, tuple>::value;
+ return __tuple_constructible<_Tuple, tuple>::value
+ && __tuple_convertible<_Tuple, tuple>::value;
}
template <class _Tuple>
@@ -577,6 +585,7 @@
template <class _Tuple>
static constexpr bool __enable_implicit() {
return _And<
+ __tuple_constructible<_Tuple, tuple>,
__tuple_convertible<_Tuple, tuple>,
_PreferTupleLikeConstructor<_Tuple>
>::value;
diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_move.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_move.pass.cpp
index f343201..2c24f78 100644
--- a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_move.pass.cpp
+++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_move.pass.cpp
@@ -46,6 +46,20 @@
explicit D(int i) : B(i) {}
};
+struct BonkersBananas {
+ template <class T>
+ operator T() &&;
+ template <class T, class = void>
+ explicit operator T() && = delete;
+};
+
+void test_bonkers_bananas_conversion() {
+ using ReturnType = std::tuple<int, int>;
+ static_assert(std::is_convertible<BonkersBananas, ReturnType>(), "");
+ static_assert(!std::is_constructible<ReturnType, BonkersBananas>(), "");
+
+}
+
int main(int, char**)
{
{