|
@@ -15,24 +15,74 @@
|
|
// template <class TupleLike> tuple(TupleLike&&); // libc++ extension
|
|
// template <class TupleLike> tuple(TupleLike&&); // libc++ extension
|
|
|
|
|
|
// See llvm.org/PR31384
|
|
// See llvm.org/PR31384
|
|
-
|
|
|
|
#include <tuple>
|
|
#include <tuple>
|
|
#include <cassert>
|
|
#include <cassert>
|
|
|
|
|
|
-
|
|
|
|
int count = 0;
|
|
int count = 0;
|
|
|
|
|
|
|
|
+struct Explicit {
|
|
|
|
+ Explicit() = default;
|
|
|
|
+ explicit Explicit(int) {}
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+struct Implicit {
|
|
|
|
+ Implicit() = default;
|
|
|
|
+ Implicit(int) {}
|
|
|
|
+};
|
|
|
|
+
|
|
template<class T>
|
|
template<class T>
|
|
-struct derived : std::tuple<T> {
|
|
|
|
|
|
+struct Derived : std::tuple<T> {
|
|
using std::tuple<T>::tuple;
|
|
using std::tuple<T>::tuple;
|
|
template<class U>
|
|
template<class U>
|
|
- operator std::tuple<U>() && {
|
|
|
|
- ++count;
|
|
|
|
- return {};
|
|
|
|
- }
|
|
|
|
|
|
+ operator std::tuple<U>() && { ++count; return {}; }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+template<class T>
|
|
|
|
+struct ExplicitDerived : std::tuple<T> {
|
|
|
|
+ using std::tuple<T>::tuple;
|
|
|
|
+ template<class U>
|
|
|
|
+ explicit operator std::tuple<U>() && { ++count; return {}; }
|
|
};
|
|
};
|
|
|
|
|
|
int main() {
|
|
int main() {
|
|
- std::tuple<int> foo = derived<int&&>{42};
|
|
|
|
- assert(count == 1);
|
|
|
|
|
|
+ {
|
|
|
|
+ std::tuple<Explicit> foo = Derived<int>{42};
|
|
|
|
+ assert(count == 1);
|
|
|
|
+ std::tuple<Explicit> bar(Derived<int>{42});
|
|
|
|
+ assert(count == 2);
|
|
|
|
+ }
|
|
|
|
+ count = 0;
|
|
|
|
+ {
|
|
|
|
+ std::tuple<Implicit> foo = Derived<int>{42};
|
|
|
|
+ assert(count == 1);
|
|
|
|
+ std::tuple<Implicit> bar(Derived<int>{42});
|
|
|
|
+ assert(count == 2);
|
|
|
|
+ }
|
|
|
|
+ count = 0;
|
|
|
|
+ {
|
|
|
|
+ static_assert(!std::is_convertible<
|
|
|
|
+ ExplicitDerived<int>, std::tuple<Explicit>>::value, "");
|
|
|
|
+ std::tuple<Explicit> bar(ExplicitDerived<int>{42});
|
|
|
|
+ assert(count == 1);
|
|
|
|
+ }
|
|
|
|
+ count = 0;
|
|
|
|
+ {
|
|
|
|
+ // FIXME: Libc++ incorrectly rejects this code.
|
|
|
|
+#ifndef _LIBCPP_VERSION
|
|
|
|
+ std::tuple<Implicit> foo = ExplicitDerived<int>{42};
|
|
|
|
+ static_assert(std::is_convertible<
|
|
|
|
+ ExplicitDerived<int>, std::tuple<Implicit>>::value,
|
|
|
|
+ "correct STLs accept this");
|
|
|
|
+#else
|
|
|
|
+ static_assert(!std::is_convertible<
|
|
|
|
+ ExplicitDerived<int>, std::tuple<Implicit>>::value,
|
|
|
|
+ "libc++ incorrectly rejects this");
|
|
|
|
+#endif
|
|
|
|
+ assert(count == 0);
|
|
|
|
+ std::tuple<Implicit> bar(ExplicitDerived<int>{42});
|
|
|
|
+ assert(count == 1);
|
|
|
|
+ }
|
|
|
|
+ count = 0;
|
|
|
|
+
|
|
}
|
|
}
|