-
Notifications
You must be signed in to change notification settings - Fork 12.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement C++17 <variant>. Patch from Michael Park!
This patch was reviewed as https://reviews.llvm.org/D23263. llvm-svn: 288547
- Loading branch information
Showing
30 changed files
with
2,374 additions
and
164 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| //===------------------------ variant.cpp ---------------------------------===// | ||
| // | ||
| // 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. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "variant" | ||
|
|
||
| namespace std { | ||
|
|
||
| const char* bad_variant_access::what() const noexcept { | ||
| return "bad_variant_access"; | ||
| } | ||
|
|
||
| } // namespace std |
181 changes: 181 additions & 0 deletions
181
libcxx/test/libcxx/utilities/variant/variant.variant/variant.assign/copy.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,181 @@ | ||
| // -*- 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 | ||
|
|
||
| // <variant> | ||
|
|
||
| // template <class ...Types> class variant; | ||
|
|
||
| // variant& operator=(variant const&); | ||
|
|
||
| #include <type_traits> | ||
| #include <variant> | ||
|
|
||
| #include "test_macros.h" | ||
|
|
||
| struct NTCopyAssign { | ||
| constexpr NTCopyAssign(int v) : value(v) {} | ||
| NTCopyAssign(const NTCopyAssign &) = default; | ||
| NTCopyAssign(NTCopyAssign &&) = default; | ||
| NTCopyAssign &operator=(const NTCopyAssign &that) { | ||
| value = that.value; | ||
| return *this; | ||
| }; | ||
| NTCopyAssign &operator=(NTCopyAssign &&) = delete; | ||
| int value; | ||
| }; | ||
|
|
||
| static_assert(!std::is_trivially_copy_assignable<NTCopyAssign>::value, ""); | ||
| static_assert(std::is_copy_assignable<NTCopyAssign>::value, ""); | ||
|
|
||
| struct TCopyAssign { | ||
| constexpr TCopyAssign(int v) : value(v) {} | ||
| TCopyAssign(const TCopyAssign &) = default; | ||
| TCopyAssign(TCopyAssign &&) = default; | ||
| TCopyAssign &operator=(const TCopyAssign &) = default; | ||
| TCopyAssign &operator=(TCopyAssign &&) = delete; | ||
| int value; | ||
| }; | ||
|
|
||
| static_assert(std::is_trivially_copy_assignable<TCopyAssign>::value, ""); | ||
|
|
||
| struct TCopyAssignNTMoveAssign { | ||
| constexpr TCopyAssignNTMoveAssign(int v) : value(v) {} | ||
| TCopyAssignNTMoveAssign(const TCopyAssignNTMoveAssign &) = default; | ||
| TCopyAssignNTMoveAssign(TCopyAssignNTMoveAssign &&) = default; | ||
| TCopyAssignNTMoveAssign &operator=(const TCopyAssignNTMoveAssign &) = default; | ||
| TCopyAssignNTMoveAssign &operator=(TCopyAssignNTMoveAssign &&that) { | ||
| value = that.value; | ||
| that.value = -1; | ||
| return *this; | ||
| } | ||
| int value; | ||
| }; | ||
|
|
||
| static_assert(std::is_trivially_copy_assignable_v<TCopyAssignNTMoveAssign>); | ||
|
|
||
| void test_copy_assignment_sfinae() { | ||
| { | ||
| using V = std::variant<int, long>; | ||
| static_assert(std::is_trivially_copy_assignable<V>::value, ""); | ||
| } | ||
| { | ||
| using V = std::variant<int, NTCopyAssign>; | ||
| static_assert(!std::is_trivially_copy_assignable<V>::value, ""); | ||
| static_assert(std::is_copy_assignable<V>::value, ""); | ||
| } | ||
| { | ||
| using V = std::variant<int, TCopyAssign>; | ||
| static_assert(std::is_trivially_copy_assignable<V>::value, ""); | ||
| } | ||
| { | ||
| using V = std::variant<int, TCopyAssignNTMoveAssign>; | ||
| static_assert(std::is_trivially_copy_assignable<V>::value, ""); | ||
| } | ||
| } | ||
|
|
||
| template <typename T> struct Result { size_t index; T value; }; | ||
|
|
||
| void test_copy_assignment_same_index() { | ||
| { | ||
| struct { | ||
| constexpr Result<int> operator()() const { | ||
| using V = std::variant<int>; | ||
| V v(43); | ||
| V v2(42); | ||
| v = 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<long> operator()() const { | ||
| using V = std::variant<int, long, unsigned>; | ||
| V v(43l); | ||
| V v2(42l); | ||
| v = 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<int> operator()() const { | ||
| using V = std::variant<int, TCopyAssign, unsigned>; | ||
| V v(std::in_place_type<TCopyAssign>, 43); | ||
| V v2(std::in_place_type<TCopyAssign>, 42); | ||
| v = v2; | ||
| return {v.index(), std::get<1>(v).value}; | ||
| } | ||
| } test; | ||
| constexpr auto result = test(); | ||
| static_assert(result.index == 1); | ||
| static_assert(result.value == 42); | ||
| } | ||
| { | ||
| struct { | ||
| constexpr Result<int> operator()() const { | ||
| using V = std::variant<int, TCopyAssignNTMoveAssign, unsigned>; | ||
| V v(std::in_place_type<TCopyAssignNTMoveAssign>, 43); | ||
| V v2(std::in_place_type<TCopyAssignNTMoveAssign>, 42); | ||
| v = 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_copy_assignment_different_index() { | ||
| { | ||
| struct { | ||
| constexpr Result<long> operator()() const { | ||
| using V = std::variant<int, long, unsigned>; | ||
| V v(43); | ||
| V v2(42l); | ||
| v = 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<int> operator()() const { | ||
| using V = std::variant<int, TCopyAssign, unsigned>; | ||
| V v(std::in_place_type<unsigned>, 43); | ||
| V v2(std::in_place_type<TCopyAssign>, 42); | ||
| v = 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_copy_assignment_same_index(); | ||
| test_copy_assignment_different_index(); | ||
| test_copy_assignment_sfinae(); | ||
| } |
167 changes: 167 additions & 0 deletions
167
libcxx/test/libcxx/utilities/variant/variant.variant/variant.assign/move.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,167 @@ | ||
| // -*- 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 | ||
|
|
||
| // <variant> | ||
|
|
||
| // template <class ...Types> class variant; | ||
|
|
||
| // variant& operator=(variant&&) noexcept(see below); | ||
|
|
||
| #include <type_traits> | ||
| #include <variant> | ||
|
|
||
| #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<NTMoveAssign>::value, ""); | ||
| static_assert(std::is_move_assignable<NTMoveAssign>::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<TMoveAssign>::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<TMoveAssignNTCopyAssign>); | ||
|
|
||
| void test_move_assignment_sfinae() { | ||
| { | ||
| using V = std::variant<int, long>; | ||
| static_assert(std::is_trivially_move_assignable<V>::value, ""); | ||
| } | ||
| { | ||
| using V = std::variant<int, NTMoveAssign>; | ||
| static_assert(!std::is_trivially_move_assignable<V>::value, ""); | ||
| static_assert(std::is_move_assignable<V>::value, ""); | ||
| } | ||
| { | ||
| using V = std::variant<int, TMoveAssign>; | ||
| static_assert(std::is_trivially_move_assignable<V>::value, ""); | ||
| } | ||
| { | ||
| using V = std::variant<int, TMoveAssignNTCopyAssign>; | ||
| static_assert(std::is_trivially_move_assignable<V>::value, ""); | ||
| } | ||
| } | ||
|
|
||
| template <typename T> struct Result { size_t index; T value; }; | ||
|
|
||
| void test_move_assignment_same_index() { | ||
| { | ||
| struct { | ||
| constexpr Result<int> operator()() const { | ||
| using V = std::variant<int>; | ||
| 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<long> operator()() const { | ||
| using V = std::variant<int, long, unsigned>; | ||
| 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<int> operator()() const { | ||
| using V = std::variant<int, TMoveAssign, unsigned>; | ||
| V v(std::in_place_type<TMoveAssign>, 43); | ||
| V v2(std::in_place_type<TMoveAssign>, 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<long> operator()() const { | ||
| using V = std::variant<int, long, unsigned>; | ||
| 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<long> operator()() const { | ||
| using V = std::variant<int, TMoveAssign, unsigned>; | ||
| V v(std::in_place_type<unsigned>, 43); | ||
| V v2(std::in_place_type<TMoveAssign>, 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(); | ||
| } |
Oops, something went wrong.