1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03 10 11 // See https://llvm.org/PR31384. 12 13 #include <tuple> 14 #include <cassert> 15 16 #include "test_macros.h" 17 18 int count = 0; 19 20 struct Explicit { 21 Explicit() = default; ExplicitExplicit22 explicit Explicit(int) {} 23 }; 24 25 struct Implicit { 26 Implicit() = default; ImplicitImplicit27 Implicit(int) {} 28 }; 29 30 template<class T> 31 struct Derived : std::tuple<T> { 32 using std::tuple<T>::tuple; 33 template<class U> operator std::tuple<U>Derived34 operator std::tuple<U>() && { ++count; return {}; } 35 }; 36 37 38 template<class T> 39 struct ExplicitDerived : std::tuple<T> { 40 using std::tuple<T>::tuple; 41 template<class U> operator std::tuple<U>ExplicitDerived42 explicit operator std::tuple<U>() && { ++count; return {}; } 43 }; 44 main(int,char **)45int main(int, char**) { 46 { 47 std::tuple<Explicit> foo = Derived<int>{42}; ((void)foo); 48 assert(count == 1); 49 Derived<int> d{42}; 50 std::tuple<Explicit> bar(std::move(d)); ((void)bar); 51 #if TEST_STD_VER < 17 52 assert(count == 1); 53 #else 54 assert(count == 2); 55 #endif 56 } 57 count = 0; 58 { 59 std::tuple<Implicit> foo = Derived<int>{42}; ((void)foo); 60 assert(count == 1); 61 Derived<int> d{42}; 62 std::tuple<Implicit> bar(std::move(d)); ((void)bar); 63 #if TEST_STD_VER < 17 64 assert(count == 1); 65 #else 66 assert(count == 2); 67 #endif 68 } 69 count = 0; 70 { 71 static_assert(!std::is_convertible<ExplicitDerived<int>, std::tuple<Explicit>>::value, ""); 72 ExplicitDerived<int> d{42}; 73 std::tuple<Explicit> bar(std::move(d)); ((void)bar); 74 #if TEST_STD_VER < 17 75 assert(count == 0); 76 #else 77 assert(count == 1); 78 #endif 79 } 80 count = 0; 81 { 82 std::tuple<Implicit> foo = ExplicitDerived<int>{42}; ((void)foo); 83 static_assert(std::is_convertible<ExplicitDerived<int>, std::tuple<Implicit>>::value, ""); 84 assert(count == 0); 85 ExplicitDerived<int> d{42}; 86 std::tuple<Implicit> bar(std::move(d)); ((void)bar); 87 #if TEST_STD_VER < 17 88 assert(count == 0); 89 #else 90 assert(count == 1); 91 #endif 92 } 93 count = 0; 94 95 return 0; 96 } 97