value.pass.cpp revision 856947863f062ea4b2213a071f7db620a61582ab
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 BadTag = std::in_place_type_t<int>;
112    using OKTag = std::in_place_t;
113    using OKDecay = std::decay_t<OKTag>;
114    // Test that the tag type is properly handled in SFINAE
115    BadTag t = std::in_place;
116    OKTag ot = std::in_place;
117    {
118        std::any a(t);
119        assertContains<int>(a, 0);
120    }
121    {
122        std::any a(std::move(t));
123        assertContains<int>(a, 0);
124    }
125    {
126        std::any a(ot);
127        assertContains<OKDecay>(a, ot);
128    }
129    {
130        OKDecay d = ot;
131        std::any a(d);
132        assertContains<OKDecay>(a, ot);
133    }
134    {
135        struct Dummy { Dummy() = delete; };
136        using T = std::in_place_type_t<Dummy>;
137        static_assert(!std::is_constructible<std::any, T>::value, "");
138    }
139    {
140        // Test that the ValueType&& constructor SFINAE's away when the
141        // argument is non-copyable
142        struct NoCopy {
143          NoCopy() = default;
144          NoCopy(NoCopy const&) = delete;
145          NoCopy(int) {}
146        };
147        static_assert(!std::is_constructible<std::any, NoCopy>::value, "");
148        static_assert(!std::is_constructible<std::any, NoCopy&>::value, "");
149        static_assert(!std::is_convertible<NoCopy, std::any>::value, "");
150    }
151}
152
153int main() {
154    test_copy_move_value<small>();
155    test_copy_move_value<large>();
156    test_copy_value_throws<small_throws_on_copy>();
157    test_copy_value_throws<large_throws_on_copy>();
158    test_move_value_throws();
159    test_sfinae_constraints();
160}