1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // The LLVM Compiler Infrastructure 5 // 6 // This file is dual licensed under the MIT and the University of Illinois Open 7 // Source Licenses. See LICENSE.TXT for details. 8 // 9 //===----------------------------------------------------------------------===// 10 11 // UNSUPPORTED: c++98, c++03 12 13 // <tuple> 14 15 // template <class TupleLike> tuple(TupleLike&&); // libc++ extension 16 17 // See llvm.org/PR31384 18 #include <tuple> 19 #include <cassert> 20 21 int count = 0; 22 23 struct Explicit { 24 Explicit() = default; ExplicitExplicit25 explicit Explicit(int) {} 26 }; 27 28 struct Implicit { 29 Implicit() = default; ImplicitImplicit30 Implicit(int) {} 31 }; 32 33 template<class T> 34 struct Derived : std::tuple<T> { 35 using std::tuple<T>::tuple; 36 template<class U> operator std::tuple<U>Derived37 operator std::tuple<U>() && { ++count; return {}; } 38 }; 39 40 41 template<class T> 42 struct ExplicitDerived : std::tuple<T> { 43 using std::tuple<T>::tuple; 44 template<class U> operator std::tuple<U>ExplicitDerived45 explicit operator std::tuple<U>() && { ++count; return {}; } 46 }; 47 main()48int main() { 49 { 50 std::tuple<Explicit> foo = Derived<int>{42}; ((void)foo); 51 assert(count == 1); 52 std::tuple<Explicit> bar(Derived<int>{42}); ((void)bar); 53 assert(count == 2); 54 } 55 count = 0; 56 { 57 std::tuple<Implicit> foo = Derived<int>{42}; ((void)foo); 58 assert(count == 1); 59 std::tuple<Implicit> bar(Derived<int>{42}); ((void)bar); 60 assert(count == 2); 61 } 62 count = 0; 63 { 64 static_assert(!std::is_convertible< 65 ExplicitDerived<int>, std::tuple<Explicit>>::value, ""); 66 std::tuple<Explicit> bar(ExplicitDerived<int>{42}); ((void)bar); 67 assert(count == 1); 68 } 69 count = 0; 70 { 71 // FIXME: Libc++ incorrectly rejects this code. 72 #ifndef _LIBCPP_VERSION 73 std::tuple<Implicit> foo = ExplicitDerived<int>{42}; ((void)foo); 74 static_assert(std::is_convertible< 75 ExplicitDerived<int>, std::tuple<Implicit>>::value, 76 "correct STLs accept this"); 77 #else 78 static_assert(!std::is_convertible< 79 ExplicitDerived<int>, std::tuple<Implicit>>::value, 80 "libc++ incorrectly rejects this"); 81 #endif 82 assert(count == 0); 83 std::tuple<Implicit> bar(ExplicitDerived<int>{42}); ((void)bar); 84 assert(count == 1); 85 } 86 count = 0; 87 88 } 89