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.cons/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.cons/value.pass.cpp')
-rw-r--r-- | libcxx/test/std/utilities/any/any.class/any.cons/value.pass.cpp | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/libcxx/test/std/utilities/any/any.class/any.cons/value.pass.cpp b/libcxx/test/std/utilities/any/any.class/any.cons/value.pass.cpp new file mode 100644 index 00000000000..ba5419b1245 --- /dev/null +++ b/libcxx/test/std/utilities/any/any.class/any.cons/value.pass.cpp @@ -0,0 +1,184 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class Value> any(Value &&) + +// Test construction from a value. +// Concerns: +// --------- +// 1. The value is properly move/copied depending on the value category. +// 2. Both small and large values are properly handled. + + +#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 Type> +void test_copy_value_throws() +{ +#if !defined(TEST_HAS_NO_EXCEPTIONS) + assert(Type::count == 0); + { + Type const t(42); + assert(Type::count == 1); + try { + any const a2(t); + assert(false); + } catch (my_any_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(Type::count == 1); + assert(t.value == 42); + } + assert(Type::count == 0); +#endif +} + +void test_move_value_throws() +{ +#if !defined(TEST_HAS_NO_EXCEPTIONS) + assert(throws_on_move::count == 0); + { + throws_on_move v; + assert(throws_on_move::count == 1); + try { + any const a(std::move(v)); + assert(false); + } catch (my_any_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(throws_on_move::count == 1); + } + assert(throws_on_move::count == 0); +#endif +} + +template <class Type> +void test_copy_move_value() { + // constructing from a small type should perform no allocations. + DisableAllocationGuard g(isSmallType<Type>()); ((void)g); + assert(Type::count == 0); + Type::reset(); + { + Type t(42); + assert(Type::count == 1); + + any a(t); + + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::moved == 0); + assertContains<Type>(a, 42); + } + assert(Type::count == 0); + Type::reset(); + { + Type t(42); + assert(Type::count == 1); + + any a(std::move(t)); + + assert(Type::count == 2); + assert(Type::copied == 0); + assert(Type::moved == 1); + assertContains<Type>(a, 42); + } +} + +void test_non_moveable_type() +{ + using Type = deleted_move; + { + deleted_move mv(42); + std::any a(mv); + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::moved == 0); + assertContains<Type>(a, 42); + } + assert(Type::count == 0); + Type::reset(); + { + deleted_move mv(42); + std::any a(std::move(mv)); + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::moved == 0); + assertContains<Type>(a, 42); + } + assert(Type::count == 0); + Type::reset(); +} + + + +// Test that any(ValueType&&) is *never* selected for a std::in_place type. +void test_sfinae_constraints() { + using Tag = std::in_place_type_t<int>; +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wignored-qualifiers" +#endif + static_assert(std::is_same<Tag, const Tag>::value, ""); +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + // Test that the tag type is properly handled in SFINAE + Tag t = std::in_place; + { + std::any a(t); + assertContains<int>(a, 0); + } + { + std::any a(std::move(t)); + assertContains<int>(a, 0); + } + { + struct Dummy { Dummy() = delete; }; + using T = std::in_place_type_t<Dummy>; + static_assert(!std::is_constructible<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(int) {} + }; + static_assert(!std::is_constructible<std::any, NoCopy>::value, ""); + static_assert(!std::is_convertible<NoCopy, std::any>::value, ""); + } +} + +int main() { + test_copy_move_value<small>(); + test_copy_move_value<large>(); + test_copy_value_throws<small_throws_on_copy>(); + test_copy_value_throws<large_throws_on_copy>(); + test_move_value_throws(); + test_non_moveable_type(); + test_sfinae_constraints(); +}
\ No newline at end of file |