value.pass.cpp revision 2c429bee79204b77cff067695798dfac5605820d
1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// UNSUPPORTED: c++98, c++03, c++11, c++14
11
12// <any>
13
14// template <class Value> any(Value &&)
15
16// Test construction from a value.
17// Concerns:
18// ---------
19// 1. The value is properly move/copied depending on the value category.
20// 2. Both small and large values are properly handled.
21
22
23#include <any>
24#include <cassert>
25
26#include "any_helpers.h"
27#include "count_new.hpp"
28#include "test_macros.h"
29
30using std::any;
31using std::any_cast;
32
33template <class Type>
34void test_copy_value_throws()
35{
36#if !defined(TEST_HAS_NO_EXCEPTIONS)
37    assert(Type::count == 0);
38    {
39        Type const t(42);
40        assert(Type::count == 1);
41        try {
42            any const a2(t);
43            assert(false);
44        } catch (my_any_exception const &) {
45            // do nothing
46        } catch (...) {
47            assert(false);
48        }
49        assert(Type::count == 1);
50        assert(t.value == 42);
51    }
52    assert(Type::count == 0);
53#endif
54}
55
56void test_move_value_throws()
57{
58#if !defined(TEST_HAS_NO_EXCEPTIONS)
59    assert(throws_on_move::count == 0);
60    {
61        throws_on_move v;
62        assert(throws_on_move::count == 1);
63        try {
64            any const a(std::move(v));
65            assert(false);
66        } catch (my_any_exception const &) {
67            // do nothing
68        } catch (...) {
69            assert(false);
70        }
71        assert(throws_on_move::count == 1);
72    }
73    assert(throws_on_move::count == 0);
74#endif
75}
76
77template <class Type>
78void test_copy_move_value() {
79    // constructing from a small type should perform no allocations.
80    DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
81    assert(Type::count == 0);
82    Type::reset();
83    {
84        Type t(42);
85        assert(Type::count == 1);
86
87        any a(t);
88
89        assert(Type::count == 2);
90        assert(Type::copied == 1);
91        assert(Type::moved == 0);
92        assertContains<Type>(a, 42);
93    }
94    assert(Type::count == 0);
95    Type::reset();
96    {
97        Type t(42);
98        assert(Type::count == 1);
99
100        any a(std::move(t));
101
102        assert(Type::count == 2);
103        assert(Type::copied == 0);
104        assert(Type::moved == 1);
105        assertContains<Type>(a, 42);
106    }
107}
108
109// Test that any(ValueType&&) is *never* selected for a std::in_place type.
110void test_sfinae_constraints() {
111    using Tag = std::in_place_type_t<int>;
112#if defined(__clang__)
113#pragma clang diagnostic push
114#pragma clang diagnostic ignored "-Wignored-qualifiers"
115#endif
116    static_assert(std::is_same<Tag, const Tag>::value, "");
117#if defined(__clang__)
118#pragma clang diagnostic pop
119#endif
120    // Test that the tag type is properly handled in SFINAE
121    Tag t = std::in_place;
122    {
123        std::any a(t);
124        assertContains<int>(a, 0);
125    }
126    {
127        std::any a(std::move(t));
128        assertContains<int>(a, 0);
129    }
130    {
131        struct Dummy { Dummy() = delete; };
132        using T = std::in_place_type_t<Dummy>;
133        static_assert(!std::is_constructible<std::any, T>::value, "");
134    }
135    {
136        // Test that the ValueType&& constructor SFINAE's away when the
137        // argument is non-copyable
138        struct NoCopy {
139          NoCopy() = default;
140          NoCopy(NoCopy const&) = delete;
141          NoCopy(int) {}
142        };
143        static_assert(!std::is_constructible<std::any, NoCopy>::value, "");
144        static_assert(!std::is_constructible<std::any, NoCopy&>::value, "");
145        static_assert(!std::is_convertible<NoCopy, std::any>::value, "");
146    }
147}
148
149int main() {
150    test_copy_move_value<small>();
151    test_copy_move_value<large>();
152    test_copy_value_throws<small_throws_on_copy>();
153    test_copy_value_throws<large_throws_on_copy>();
154    test_move_value_throws();
155    test_sfinae_constraints();
156}