diff options
author | Eric Fiselier <eric@efcs.ca> | 2016-08-11 03:13:11 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2016-08-11 03:13:11 +0000 |
commit | 324506b9f3a414487f8ba8e128f7aac038412e4f (patch) | |
tree | cd8522d7bfd47cce6b722d19e669b86a62ef7deb /libcxx/test/std/utilities/any/any.class/any.assign/value.pass.cpp | |
parent | 25fb5bda0f4c03ce71e6ddbaf09e12af558b5eda (diff) | |
download | bcm5719-llvm-324506b9f3a414487f8ba8e128f7aac038412e4f.tar.gz bcm5719-llvm-324506b9f3a414487f8ba8e128f7aac038412e4f.zip |
[libcxx] Add std::any
Summary:
This patch adds std::any by moving/adapting <experimental/any>.
This patch also implements the std::any parts of p0032r3 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0032r3.pdf)
and LWG 2509 (http://cplusplus.github.io/LWG/lwg-defects.html#2509).
I plan to push it in a day or two if there are no comments.
Reviewers: mclow.lists, EricWF
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D22733
llvm-svn: 278310
Diffstat (limited to 'libcxx/test/std/utilities/any/any.class/any.assign/value.pass.cpp')
-rw-r--r-- | libcxx/test/std/utilities/any/any.class/any.assign/value.pass.cpp | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/libcxx/test/std/utilities/any/any.class/any.assign/value.pass.cpp b/libcxx/test/std/utilities/any/any.class/any.assign/value.pass.cpp new file mode 100644 index 00000000000..d844fcfaa7c --- /dev/null +++ b/libcxx/test/std/utilities/any/any.class/any.assign/value.pass.cpp @@ -0,0 +1,205 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// <any> + +// any& operator=(any const &); + +// Test value copy and move assignment. + +#include <any> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::any; +using std::any_cast; + +template <class LHS, class RHS> +void test_assign_value() { + assert(LHS::count == 0); + assert(RHS::count == 0); + LHS::reset(); + RHS::reset(); + { + any lhs(LHS(1)); + any const rhs(RHS(2)); + + assert(LHS::count == 1); + assert(RHS::count == 1); + assert(RHS::copied == 0); + + lhs = rhs; + + assert(RHS::copied == 1); + assert(LHS::count == 0); + assert(RHS::count == 2); + + assertContains<RHS>(lhs, 2); + assertContains<RHS>(rhs, 2); + } + assert(LHS::count == 0); + assert(RHS::count == 0); + LHS::reset(); + RHS::reset(); + { + any lhs(LHS(1)); + any rhs(RHS(2)); + + assert(LHS::count == 1); + assert(RHS::count == 1); + assert(RHS::moved == 1); + + lhs = std::move(rhs); + + assert(RHS::moved >= 1); + assert(RHS::copied == 0); + assert(LHS::count == 0); + assert(RHS::count == 1); + + assertContains<RHS>(lhs, 2); + assertEmpty<RHS>(rhs); + } + assert(LHS::count == 0); + assert(RHS::count == 0); +} + +template <class RHS> +void test_assign_value_empty() { + assert(RHS::count == 0); + RHS::reset(); + { + any lhs; + RHS rhs(42); + assert(RHS::count == 1); + assert(RHS::copied == 0); + + lhs = rhs; + + assert(RHS::count == 2); + assert(RHS::copied == 1); + assert(RHS::moved >= 0); + assertContains<RHS>(lhs, 42); + } + assert(RHS::count == 0); + RHS::reset(); + { + any lhs; + RHS rhs(42); + assert(RHS::count == 1); + assert(RHS::moved == 0); + + lhs = std::move(rhs); + + assert(RHS::count == 2); + assert(RHS::copied == 0); + assert(RHS::moved >= 1); + assertContains<RHS>(lhs, 42); + } + assert(RHS::count == 0); + RHS::reset(); +} + + +template <class Tp, bool Move = false> +void test_assign_throws() { +#if !defined(TEST_HAS_NO_EXCEPTIONS) + auto try_throw= + [](any& lhs, auto&& rhs) { + try { + Move ? lhs = std::move(rhs) + : lhs = rhs; + assert(false); + } catch (my_any_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + }; + // const lvalue to empty + { + any lhs; + Tp rhs(1); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(Tp::count == 1); + assertEmpty<Tp>(lhs); + } + { + any lhs((small(2))); + Tp rhs(1); + assert(small::count == 1); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(small::count == 1); + assert(Tp::count == 1); + assertContains<small>(lhs, 2); + } + { + any lhs((large(2))); + Tp rhs(1); + assert(large::count == 1); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(large::count == 1); + assert(Tp::count == 1); + assertContains<large>(lhs, 2); + } +#endif +} + + +// Test that any& operator=(ValueType&&) is *never* selected for: +// * std::in_place type. +// * Non-copyable types +void test_sfinae_constraints() { + { + using Tag = std::in_place_type_t<int>; + using RawTag = std::remove_reference_t<Tag>; + static_assert(!std::is_assignable<std::any, RawTag&&>::value, ""); + } + { + struct Dummy { Dummy() = delete; }; + using T = std::in_place_type_t<Dummy>; + static_assert(!std::is_assignable<std::any, T>::value, ""); + } + { + // Test that the ValueType&& constructor SFINAE's away when the + // argument is non-copyable + struct NoCopy { + NoCopy() = default; + NoCopy(NoCopy const&) = delete; + NoCopy(NoCopy&&) = default; + }; + static_assert(!std::is_assignable<std::any, NoCopy>::value, ""); + } +} + +int main() { + test_assign_value<small1, small2>(); + test_assign_value<large1, large2>(); + test_assign_value<small, large>(); + test_assign_value<large, small>(); + test_assign_value_empty<small>(); + test_assign_value_empty<large>(); + test_assign_throws<small_throws_on_copy>(); + test_assign_throws<large_throws_on_copy>(); + test_assign_throws<throws_on_move, /* Move = */ true>(); + test_sfinae_constraints(); +}
\ No newline at end of file |