//===----------------------------------------------------------------------===// // // 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(allocator_arg_t, const Alloc& a, // 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_allocator.h" #include "test_macros.h" // test: The expression inside explicit is equivalent to: // !(is_convertible_v(FWD(u))), Types> && ...) static_assert(ImplicitlyConstructible< std::tuple>, std::allocator_arg_t, const test_allocator&, const std::tuple&&>); static_assert( ImplicitlyConstructible< std::tuple, ConvertibleFrom>, std::allocator_arg_t, const test_allocator&, const std::tuple&&>); static_assert(!ImplicitlyConstructible>, std::allocator_arg_t, const test_allocator&, const std::tuple&&>); static_assert(!ImplicitlyConstructible, ConvertibleFrom>, std::allocator_arg_t, const test_allocator&, const std::tuple&&>); constexpr bool test() { // test implicit conversions. // sizeof...(Types) == 1 { const std::tuple t1{1}; std::tuple> t2 = {std::allocator_arg, test_allocator{}, std::move(t1)}; assert(std::get<0>(t2).v.val == 1); assert(std::get<0>(t2).alloc_constructed); } // test implicit conversions. // sizeof...(Types) > 1 { const std::tuple t1{1, 2}; std::tuple, int> t2 = {std::allocator_arg_t{}, test_allocator{}, std::move(t1)}; assert(std::get<0>(t2).v.val == 1); assert(std::get<1>(t2) == 2); assert(std::get<0>(t2).alloc_constructed); } // test explicit conversions. // sizeof...(Types) == 1 { const std::tuple t1{1}; std::tuple> t2{std::allocator_arg_t{}, test_allocator{}, std::move(t1)}; assert(std::get<0>(t2).v.val == 1); assert(std::get<0>(t2).alloc_constructed); } // test explicit conversions. // sizeof...(Types) > 1 { const std::tuple t1{1, 2}; std::tuple, int> t2{std::allocator_arg_t{}, test_allocator{}, std::move(t1)}; assert(std::get<0>(t2).v.val == 1); assert(std::get<1>(t2) == 2); assert(std::get<0>(t2).alloc_constructed); } // test constraints // sizeof...(Types) != sizeof...(UTypes) static_assert(!std::is_constructible_v, std::allocator_arg_t, const test_allocator&, const std::tuple&&>); static_assert(!std::is_constructible_v, std::allocator_arg_t, const test_allocator&, const std::tuple&&>); // !(is_constructible_v(FWD(u)))> && ...) static_assert(!std::is_constructible_v< std::tuple, std::allocator_arg_t, const test_allocator&, const std::tuple&&>); // sizeof...(Types) == 1 && other branch of "||" satisfied { const std::tuple t1{}; std::tuple> t2{std::allocator_arg_t{}, test_allocator{}, std::move(t1)}; assert(constMoveCtrCalled(std::get<0>(t2).v)); assert(std::get<0>(t2).alloc_constructed); } // sizeof...(Types) == 1 && is_same_v { const std::tuple t1{}; std::tuple t2{std::allocator_arg_t{}, test_allocator{}, std::move(t1)}; assert(!constMoveCtrCalled(std::get<0>(t2))); assert(std::get<0>(t2).alloc_constructed); } // sizeof...(Types) != 1 { const std::tuple t1{}; std::tuple t2{std::allocator_arg_t{}, test_allocator{}, std::move(t1)}; assert(constMoveCtrCalled(std::get<0>(std::move(t2)))); assert(std::get<0>(t2).alloc_constructed); } // 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::allocator_arg_t{}, test_allocator{}, std::move(t1)}; assert(!constMoveCtrCalled(std::get<0>(t2).v)); assert(std::get<0>(t2).alloc_constructed); } // sizeof...(Types) == 1 && is_constructible_v { const std::tuple t1{}; std::tuple> t2{std::allocator_arg_t{}, test_allocator{}, std::move(t1)}; assert(!constMoveCtrCalled(std::get<0>(t2).v)); assert(std::get<0>(t2).alloc_constructed); } #endif return true; } int main(int, char**) { test(); static_assert(test()); return 0; }