//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // template // template // constexpr explicit(see below) tuple::tuple(const // tuple&&); // // Constraints: // sizeof...(Types) equals sizeof...(UTypes) && // (is_constructible_v(FWD(u)))> && ...) is true && // ( // sizeof...(Types) is not 1 || // ( // !is_convertible_v && // !is_constructible_v && // !is_same_v // ) // ) // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 #include #include #include "copy_move_types.h" #include "test_macros.h" // test: The expression inside explicit is equivalent to: // !(is_convertible_v(FWD(u))), Types> && ...) static_assert(std::is_convertible_v&&, std::tuple>>); static_assert(std::is_convertible_v&&, std::tuple, ConvertibleFrom>>); static_assert( !std::is_convertible_v&&, std::tuple>>); static_assert(!std::is_convertible_v&&, std::tuple, ExplicitConstructibleFrom>>); constexpr bool test() { // test implicit conversions. // sizeof...(Types) == 1 { const std::tuple t1{1}; std::tuple> t2 = std::move(t1); assert(std::get<0>(t2).v.val == 1); } // test implicit conversions. // sizeof...(Types) > 1 { const std::tuple t1{1, 2}; std::tuple, int> t2 = std::move(t1); assert(std::get<0>(t2).v.val == 1); assert(std::get<1>(t2) == 2); } // test explicit conversions. // sizeof...(Types) == 1 { const std::tuple t1{1}; std::tuple> t2{std::move(t1)}; assert(std::get<0>(t2).v.val == 1); } // test explicit conversions. // sizeof...(Types) > 1 { const std::tuple t1{1, 2}; std::tuple, int> t2{std::move(t1)}; assert(std::get<0>(t2).v.val == 1); assert(std::get<1>(t2) == 2); } // test constraints // sizeof...(Types) != sizeof...(UTypes) static_assert(!std::is_constructible_v, const std::tuple&&>); static_assert(!std::is_constructible_v, const std::tuple&&>); // !(is_constructible_v(FWD(u)))> && ...) static_assert(!std::is_constructible_v, const std::tuple&&>); // sizeof...(Types) == 1 && other branch of "||" satisfied { const std::tuple t1{}; std::tuple> t2{std::move(t1)}; assert(constMoveCtrCalled(std::get<0>(t2).v)); } // sizeof...(Types) == 1 && is_same_v { const std::tuple t1{}; std::tuple t2{t1}; assert(!constMoveCtrCalled(std::get<0>(t2))); } // sizeof...(Types) != 1 { const std::tuple t1{}; std::tuple t2{std::move(t1)}; assert(constMoveCtrCalled(std::get<0>(t2))); } // These two test points cause gcc to ICE #if !defined(TEST_COMPILER_GCC) // sizeof...(Types) == 1 && is_convertible_v { const std::tuple t1{}; std::tuple> t2{std::move(t1)}; assert(!constMoveCtrCalled(std::get<0>(t2).v)); } // sizeof...(Types) == 1 && is_constructible_v { const std::tuple t1{}; std::tuple> t2{std::move(t1)}; assert(!constMoveCtrCalled(std::get<0>(t2).v)); } #endif return true; } int main(int, char**) { test(); static_assert(test()); return 0; }