brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.8 KiB · 135045d Raw
150 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// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2010 11// <utility>12 13// template <class T1, class T2> struct pair14 15// template <pair-like P>16// constexpr explicit(see-below) pair(P&&); // since C++2317 18#include <array>19#include <cassert>20#include <ranges>21#include <string>22#include <tuple>23#include <type_traits>24#include <utility>25 26namespace my_ns{27 28struct MyPairLike {29 30template <std::size_t N>31friend int get(MyPairLike const&)32{33  return 0;34}35 36};37 38} // namespace my_ns39 40template <>41struct std::tuple_size<my_ns::MyPairLike> : std::integral_constant<std::size_t, 2> {};42 43template <std::size_t N>44struct std::tuple_element<N, my_ns::MyPairLike> {45  using type = int;46};47 48// https://llvm.org/PR6562049// This used to be a hard error50static_assert(!std::is_constructible_v<std::pair<int,int>, my_ns::MyPairLike const&>);51 52 53constexpr bool test() {54  // Make sure construction works from array, tuple, and ranges::subrange55  {56    // Check from std::array57    {58      std::array<int, 2> a = {1, 2};59      std::pair<int, int> p(a);60      assert(p.first == 1);61      assert(p.second == 2);62      static_assert(!std::is_constructible_v<std::pair<int, int>, std::array<int, 1>>); // too small63      static_assert( std::is_constructible_v<std::pair<int, int>, std::array<int, 2>>); // works (test the test)64      static_assert(!std::is_constructible_v<std::pair<int, int>, std::array<int, 3>>); // too large65    }66 67    // Check from std::tuple68    {69      std::tuple<int, int> a = {1, 2};70      std::pair<int, int> p(a);71      assert(p.first == 1);72      assert(p.second == 2);73      static_assert(!std::is_constructible_v<std::pair<int, int>, std::tuple<int>>); // too small74      static_assert( std::is_constructible_v<std::pair<int, int>, std::tuple<int, int>>); // works (test the test)75      static_assert(!std::is_constructible_v<std::pair<int, int>, std::tuple<int, int, int>>); // too large76    }77 78    // Check that the constructor excludes ranges::subrange79    {80      int data[] = {1, 2, 3, 4, 5};81      const std::ranges::subrange a(data);82      // Note the expression below would be ambiguous if pair's83      // constructor does not exclude subrange84      std::pair<int*, int*> p = a;85      assert(p.first == data + 0);86      assert(p.second == data + 5);87    }88  }89 90  // Make sure we allow element conversion from a pair-like91  {92    std::tuple<int, char const*> a = {34, "hello world"};93    std::pair<long, std::string> p(a);94    assert(p.first == 34);95    assert(p.second == std::string("hello world"));96    static_assert(!std::is_constructible_v<std::pair<long, std::string>, std::tuple<char*, std::string>>); // first not convertible97    static_assert(!std::is_constructible_v<std::pair<long, std::string>, std::tuple<long, void*>>); // second not convertible98    static_assert( std::is_constructible_v<std::pair<long, std::string>, std::tuple<long, std::string>>); // works (test the test)99  }100 101  // Make sure we forward the pair-like elements102  {103    struct NoCopy {104      NoCopy() = default;105      NoCopy(NoCopy const&) = delete;106      NoCopy(NoCopy&&) = default;107    };108    std::tuple<NoCopy, NoCopy> a;109    std::pair<NoCopy, NoCopy> p(std::move(a));110    (void)p;111  }112 113  // Make sure the constructor is implicit iff both elements can be converted114  {115    struct To { };116    struct FromImplicit {117      constexpr operator To() const { return To{}; }118    };119    struct FromExplicit {120      constexpr explicit operator To() const { return To{}; }121    };122    // If both are convertible, the constructor is not explicit123    {124      std::tuple<FromImplicit, float> a = {FromImplicit{}, 2.3f};125      std::pair<To, double> p = a;126      (void)p;127      static_assert(std::is_convertible_v<std::tuple<FromImplicit, float>, std::pair<To, double>>);128    }129    // Otherwise, the constructor is explicit130    {131      static_assert( std::is_constructible_v<std::pair<To, int>, std::tuple<FromExplicit, int>>);132      static_assert(!std::is_convertible_v<std::tuple<FromExplicit, int>, std::pair<To, int>>);133 134      static_assert( std::is_constructible_v<std::pair<int, To>, std::tuple<int, FromExplicit>>);135      static_assert(!std::is_convertible_v<std::tuple<int, FromExplicit>, std::pair<int, To>>);136 137      static_assert( std::is_constructible_v<std::pair<To, To>, std::tuple<FromExplicit, FromExplicit>>);138      static_assert(!std::is_convertible_v<std::tuple<FromExplicit, FromExplicit>, std::pair<To, To>>);139    }140  }141  return true;142}143 144int main(int, char**) {145  test();146  static_assert(test());147 148  return 0;149}150