// -*- C++ -*- //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++98, c++03, c++11, c++14 // // template class variant; // variant& operator=(variant&&) noexcept(see below); #include #include #include "test_macros.h" struct NTMoveAssign { constexpr NTMoveAssign(int v) : value(v) {} NTMoveAssign(const NTMoveAssign &) = default; NTMoveAssign(NTMoveAssign &&) = default; NTMoveAssign &operator=(const NTMoveAssign &that) = default; NTMoveAssign &operator=(NTMoveAssign &&that) { value = that.value; that.value = -1; return *this; }; int value; }; static_assert(!std::is_trivially_move_assignable::value, ""); static_assert(std::is_move_assignable::value, ""); struct TMoveAssign { constexpr TMoveAssign(int v) : value(v) {} TMoveAssign(const TMoveAssign &) = delete; TMoveAssign(TMoveAssign &&) = default; TMoveAssign &operator=(const TMoveAssign &) = delete; TMoveAssign &operator=(TMoveAssign &&) = default; int value; }; static_assert(std::is_trivially_move_assignable::value, ""); struct TMoveAssignNTCopyAssign { constexpr TMoveAssignNTCopyAssign(int v) : value(v) {} TMoveAssignNTCopyAssign(const TMoveAssignNTCopyAssign &) = default; TMoveAssignNTCopyAssign(TMoveAssignNTCopyAssign &&) = default; TMoveAssignNTCopyAssign &operator=(const TMoveAssignNTCopyAssign &that) { value = that.value; return *this; } TMoveAssignNTCopyAssign &operator=(TMoveAssignNTCopyAssign &&) = default; int value; }; static_assert(std::is_trivially_move_assignable_v); void test_move_assignment_sfinae() { { using V = std::variant; static_assert(std::is_trivially_move_assignable::value, ""); } { using V = std::variant; static_assert(!std::is_trivially_move_assignable::value, ""); static_assert(std::is_move_assignable::value, ""); } { using V = std::variant; static_assert(std::is_trivially_move_assignable::value, ""); } { using V = std::variant; static_assert(std::is_trivially_move_assignable::value, ""); } } template struct Result { size_t index; T value; }; void test_move_assignment_same_index() { { struct { constexpr Result operator()() const { using V = std::variant; V v(43); V v2(42); v = std::move(v2); return {v.index(), std::get<0>(v)}; } } test; constexpr auto result = test(); static_assert(result.index == 0); static_assert(result.value == 42); } { struct { constexpr Result operator()() const { using V = std::variant; V v(43l); V v2(42l); v = std::move(v2); return {v.index(), std::get<1>(v)}; } } test; constexpr auto result = test(); static_assert(result.index == 1); static_assert(result.value == 42l); } { struct { constexpr Result operator()() const { using V = std::variant; V v(std::in_place_type, 43); V v2(std::in_place_type, 42); v = std::move(v2); return {v.index(), std::get<1>(v).value}; } } test; constexpr auto result = test(); static_assert(result.index == 1); static_assert(result.value == 42); } } void test_move_assignment_different_index() { { struct { constexpr Result operator()() const { using V = std::variant; V v(43); V v2(42l); v = std::move(v2); return {v.index(), std::get<1>(v)}; } } test; constexpr auto result = test(); static_assert(result.index == 1); static_assert(result.value == 42l); } { struct { constexpr Result operator()() const { using V = std::variant; V v(std::in_place_type, 43); V v2(std::in_place_type, 42); v = std::move(v2); return {v.index(), std::get<1>(v).value}; } } test; constexpr auto result = test(); static_assert(result.index == 1); static_assert(result.value == 42); } } int main() { test_move_assignment_same_index(); test_move_assignment_different_index(); test_move_assignment_sfinae(); }