//===----------------------------------------------------------------------===// // // 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 // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // // template struct pair // template constexpr pair& operator=(P&&); // since C++23 #include #include #include #include #include #include #include #include constexpr bool test() { // Make sure assignment works from array and tuple { // Check from std::array { std::array a = {1, 2}; std::pair p; std::same_as&> decltype(auto) result = (p = a); assert(&result == &p); assert(p.first == 1); assert(p.second == 2); static_assert(!std::is_assignable_v&, std::array>); // too small static_assert( std::is_assignable_v&, std::array>); // works (test the test) static_assert(!std::is_assignable_v&, std::array>); // too large } // Check from std::tuple { std::tuple a = {1, 2}; std::pair p; std::same_as&> decltype(auto) result = (p = a); assert(&result == &p); assert(p.first == 1); assert(p.second == 2); static_assert(!std::is_assignable_v&, std::tuple>); // too small static_assert( std::is_assignable_v&, std::tuple>); // works (test the test) static_assert(!std::is_assignable_v&, std::tuple>); // too large } // Make sure it works for ranges::subrange. This actually deserves an explanation: even though // the assignment operator explicitly excludes ranges::subrange specializations, such assignments // end up working because of ranges::subrange's implicit conversion to pair-like types. // This test ensures that the interoperability works as intended. { struct Assignable { int* ptr = nullptr; Assignable() = default; constexpr Assignable(int* p) : ptr(p) { } // enable `subrange::operator pair-like` constexpr Assignable& operator=(Assignable const&) = default; }; int data[] = {1, 2, 3, 4, 5}; std::ranges::subrange a(data); std::pair p; std::same_as&> decltype(auto) result = (p = a); assert(&result == &p); assert(p.first.ptr == data); assert(p.second.ptr == data + 5); } } // Make sure we allow element conversion from a pair-like { std::tuple a = {34, "hello world"}; std::pair p; std::same_as&> decltype(auto) result = (p = a); assert(&result == &p); assert(p.first == 34); assert(p.second == std::string("hello world")); static_assert(!std::is_assignable_v&, std::tuple>); // first not convertible static_assert(!std::is_assignable_v&, std::tuple>); // second not convertible static_assert( std::is_assignable_v&, std::tuple>); // works (test the test) } // Make sure we forward the pair-like elements { struct NoCopy { NoCopy() = default; NoCopy(NoCopy const&) = delete; NoCopy(NoCopy&&) = default; NoCopy& operator=(NoCopy const&) = delete; NoCopy& operator=(NoCopy&&) = default; }; std::tuple a; std::pair p; p = std::move(a); } return true; } int main(int, char**) { test(); static_assert(test()); return 0; }