139 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// <tuple>10 11// template <class... Types>12// template <class... UTypes>13// constexpr explicit(see below) tuple<Types>::tuple(const14// tuple<UTypes...>&&);15//16// Constraints:17// sizeof...(Types) equals sizeof...(UTypes) &&18// (is_constructible_v<Types, decltype(get<I>(FWD(u)))> && ...) is true &&19// (20// sizeof...(Types) is not 1 ||21// (22// !is_convertible_v<decltype(u), T> &&23// !is_constructible_v<T, decltype(u)> &&24// !is_same_v<T, U>25// )26// )27 28// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2029 30#include <cassert>31#include <tuple>32 33#include "copy_move_types.h"34#include "test_macros.h"35 36// test: The expression inside explicit is equivalent to:37// !(is_convertible_v<decltype(get<I>(FWD(u))), Types> && ...)38static_assert(std::is_convertible_v<const std::tuple<ConstMove>&&, std::tuple<ConvertibleFrom<ConstMove>>>);39 40static_assert(std::is_convertible_v<const std::tuple<ConstMove, ConstMove>&&,41 std::tuple<ConvertibleFrom<ConstMove>, ConvertibleFrom<ConstMove>>>);42 43static_assert(44 !std::is_convertible_v<const std::tuple<MutableCopy>&&, std::tuple<ExplicitConstructibleFrom<ConstMove>>>);45 46static_assert(!std::is_convertible_v<const std::tuple<ConstMove, ConstMove>&&,47 std::tuple<ConvertibleFrom<ConstMove>, ExplicitConstructibleFrom<ConstMove>>>);48 49constexpr bool test() {50 // test implicit conversions.51 // sizeof...(Types) == 152 {53 const std::tuple<ConstMove> t1{1};54 std::tuple<ConvertibleFrom<ConstMove>> t2 = std::move(t1);55 assert(std::get<0>(t2).v.val == 1);56 }57 58 // test implicit conversions.59 // sizeof...(Types) > 160 {61 const std::tuple<ConstMove, int> t1{1, 2};62 std::tuple<ConvertibleFrom<ConstMove>, int> t2 = std::move(t1);63 assert(std::get<0>(t2).v.val == 1);64 assert(std::get<1>(t2) == 2);65 }66 67 // test explicit conversions.68 // sizeof...(Types) == 169 {70 const std::tuple<ConstMove> t1{1};71 std::tuple<ExplicitConstructibleFrom<ConstMove>> t2{std::move(t1)};72 assert(std::get<0>(t2).v.val == 1);73 }74 75 // test explicit conversions.76 // sizeof...(Types) > 177 {78 const std::tuple<ConstMove, int> t1{1, 2};79 std::tuple<ExplicitConstructibleFrom<ConstMove>, int> t2{std::move(t1)};80 assert(std::get<0>(t2).v.val == 1);81 assert(std::get<1>(t2) == 2);82 }83 84 // test constraints85 86 // sizeof...(Types) != sizeof...(UTypes)87 static_assert(!std::is_constructible_v<std::tuple<int, int>, const std::tuple<int>&&>);88 static_assert(!std::is_constructible_v<std::tuple<int, int, int>, const std::tuple<int, int>&&>);89 90 // !(is_constructible_v<Types, decltype(get<I>(FWD(u)))> && ...)91 static_assert(!std::is_constructible_v<std::tuple<int, NoConstructorFromInt>, const std::tuple<int, int>&&>);92 93 // sizeof...(Types) == 1 && other branch of "||" satisfied94 {95 const std::tuple<TracedCopyMove> t1{};96 std::tuple<ConvertibleFrom<TracedCopyMove>> t2{std::move(t1)};97 assert(constMoveCtrCalled(std::get<0>(t2).v));98 }99 100 // sizeof...(Types) == 1 && is_same_v<T, U>101 {102 const std::tuple<TracedCopyMove> t1{};103 std::tuple<TracedCopyMove> t2{t1};104 assert(!constMoveCtrCalled(std::get<0>(t2)));105 }106 107 // sizeof...(Types) != 1108 {109 const std::tuple<TracedCopyMove, TracedCopyMove> t1{};110 std::tuple<TracedCopyMove, TracedCopyMove> t2{std::move(t1)};111 assert(constMoveCtrCalled(std::get<0>(t2)));112 }113 114 // These two test points cause gcc to ICE115#if !defined(TEST_COMPILER_GCC)116 // sizeof...(Types) == 1 && is_convertible_v<decltype(u), T>117 {118 const std::tuple<CvtFromConstTupleRefRef> t1{};119 std::tuple<ConvertibleFrom<CvtFromConstTupleRefRef>> t2{std::move(t1)};120 assert(!constMoveCtrCalled(std::get<0>(t2).v));121 }122 123 // sizeof...(Types) == 1 && is_constructible_v<decltype(u), T>124 {125 const std::tuple<ExplicitCtrFromConstTupleRefRef> t1{};126 std::tuple<ConvertibleFrom<ExplicitCtrFromConstTupleRefRef>> t2{std::move(t1)};127 assert(!constMoveCtrCalled(std::get<0>(t2).v));128 }129#endif130 131 return true;132}133 134int main(int, char**) {135 test();136 static_assert(test());137 return 0;138}139