1 // Copyright Louis Dionne 2013-2017 2 // Distributed under the Boost Software License, Version 1.0. 3 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 4 5 #include <boost/hana/tuple.hpp> 6 7 #include <utility> 8 namespace hana = boost::hana; 9 10 11 // Make sure that the tuple(Yn&&...) is not preferred over copy constructors 12 // in single-element cases and other similar cases. 13 14 struct Trap1 { 15 Trap1() = default; 16 Trap1(Trap1 const&) = default; 17 #ifndef BOOST_HANA_WORKAROUND_MSVC_MULTIPLECTOR_106654 18 Trap1(Trap1&) = default; 19 #endif 20 Trap1(Trap1&&) = default; 21 22 template <typename X> Trap1Trap123 Trap1(X&&) { 24 static_assert(sizeof(X) && false, 25 "this constructor must not be instantiated"); 26 } 27 }; 28 29 struct Trap2 { 30 Trap2() = default; 31 Trap2(Trap2 const&) = default; 32 #ifndef BOOST_HANA_WORKAROUND_MSVC_MULTIPLECTOR_106654 33 Trap2(Trap2&) = default; 34 #endif 35 Trap2(Trap2&&) = default; 36 37 template <typename X> Trap2Trap238 Trap2(X) { // not by reference 39 static_assert(sizeof(X) && false, 40 "this constructor must not be instantiated"); 41 } 42 }; 43 44 struct Trap3 { 45 Trap3() = default; 46 Trap3(Trap3 const&) = default; 47 #ifndef BOOST_HANA_WORKAROUND_MSVC_MULTIPLECTOR_106654 48 Trap3(Trap3&) = default; 49 #endif 50 Trap3(Trap3&&) = default; 51 52 template <typename X> Trap3Trap353 constexpr explicit Trap3(X&&) { // explicit, and constexpr 54 static_assert(sizeof(X) && false, 55 "this constructor must not be instantiated"); 56 } 57 }; 58 59 struct Trap4 { 60 Trap4() = default; 61 template <typename Args> Trap4Trap462 constexpr explicit Trap4(Args&&) { 63 static_assert(sizeof(Args) && false, "must never be instantiated"); 64 } 65 66 Trap4(Trap4 const&) = default; 67 Trap4(Trap4&&) = default; 68 }; 69 main()70int main() { 71 { 72 hana::tuple<Trap1> tuple{}; 73 hana::tuple<Trap1> implicit_copy = tuple; 74 hana::tuple<Trap1> explicit_copy(tuple); 75 hana::tuple<Trap1> implicit_move = std::move(tuple); 76 hana::tuple<Trap1> explicit_move(std::move(tuple)); 77 78 (void)implicit_copy; 79 (void)explicit_copy; 80 (void)implicit_move; 81 (void)explicit_move; 82 } 83 84 { 85 hana::tuple<Trap2> tuple{}; 86 hana::tuple<Trap2> implicit_copy = tuple; 87 hana::tuple<Trap2> explicit_copy(tuple); 88 hana::tuple<Trap2> implicit_move = std::move(tuple); 89 hana::tuple<Trap2> explicit_move(std::move(tuple)); 90 91 (void)implicit_copy; 92 (void)explicit_copy; 93 (void)implicit_move; 94 (void)explicit_move; 95 } 96 97 { 98 hana::tuple<Trap3> tuple{}; 99 hana::tuple<Trap3> implicit_copy = tuple; 100 hana::tuple<Trap3> explicit_copy(tuple); 101 hana::tuple<Trap3> implicit_move = std::move(tuple); 102 hana::tuple<Trap3> explicit_move(std::move(tuple)); 103 104 (void)implicit_copy; 105 (void)explicit_copy; 106 (void)implicit_move; 107 (void)explicit_move; 108 } 109 110 // Just defining the structure used to cause a failure, because of the 111 // explicitly defaulted copy-constructor. 112 { 113 struct Foo { 114 Foo() = default; 115 Foo(Foo const&) = default; 116 Foo(Foo&&) = default; 117 hana::tuple<Trap4> t; 118 }; 119 } 120 } 121