summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/hana/test/tuple/cnstr.trap.cpp
blob: a088b94668383387226bddca33f2b6dbc482df49 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

#include <boost/hana/tuple.hpp>

#include <utility>
namespace hana = boost::hana;


// Make sure that the tuple(Yn&&...) is not preferred over copy constructors
// in single-element cases and other similar cases.

struct Trap1 {
    Trap1() = default;
    Trap1(Trap1 const&) = default;
#ifndef BOOST_HANA_WORKAROUND_MSVC_MULTIPLECTOR_106654
    Trap1(Trap1&) = default;
#endif
    Trap1(Trap1&&) = default;

    template <typename X>
    Trap1(X&&) {
        static_assert(sizeof(X) && false,
        "this constructor must not be instantiated");
    }
};

struct Trap2 {
    Trap2() = default;
    Trap2(Trap2 const&) = default;
#ifndef BOOST_HANA_WORKAROUND_MSVC_MULTIPLECTOR_106654
    Trap2(Trap2&) = default;
#endif
    Trap2(Trap2&&) = default;

    template <typename X>
    Trap2(X) { // not by reference
        static_assert(sizeof(X) && false,
        "this constructor must not be instantiated");
    }
};

struct Trap3 {
    Trap3() = default;
    Trap3(Trap3 const&) = default;
#ifndef BOOST_HANA_WORKAROUND_MSVC_MULTIPLECTOR_106654
    Trap3(Trap3&) = default;
#endif
    Trap3(Trap3&&) = default;

    template <typename X>
    constexpr explicit Trap3(X&&) { // explicit, and constexpr
        static_assert(sizeof(X) && false,
        "this constructor must not be instantiated");
    }
};

struct Trap4 {
    Trap4() = default;
    template <typename Args>
    constexpr explicit Trap4(Args&&) {
        static_assert(sizeof(Args) && false, "must never be instantiated");
    }

    Trap4(Trap4 const&) = default;
    Trap4(Trap4&&) = default;
};

int main() {
    {
        hana::tuple<Trap1> tuple{};
        hana::tuple<Trap1> implicit_copy = tuple;
        hana::tuple<Trap1> explicit_copy(tuple);
        hana::tuple<Trap1> implicit_move = std::move(tuple);
        hana::tuple<Trap1> explicit_move(std::move(tuple));

        (void)implicit_copy;
        (void)explicit_copy;
        (void)implicit_move;
        (void)explicit_move;
    }

    {
        hana::tuple<Trap2> tuple{};
        hana::tuple<Trap2> implicit_copy = tuple;
        hana::tuple<Trap2> explicit_copy(tuple);
        hana::tuple<Trap2> implicit_move = std::move(tuple);
        hana::tuple<Trap2> explicit_move(std::move(tuple));

        (void)implicit_copy;
        (void)explicit_copy;
        (void)implicit_move;
        (void)explicit_move;
    }

    {
        hana::tuple<Trap3> tuple{};
        hana::tuple<Trap3> implicit_copy = tuple;
        hana::tuple<Trap3> explicit_copy(tuple);
        hana::tuple<Trap3> implicit_move = std::move(tuple);
        hana::tuple<Trap3> explicit_move(std::move(tuple));

        (void)implicit_copy;
        (void)explicit_copy;
        (void)implicit_move;
        (void)explicit_move;
    }

    // Just defining the structure used to cause a failure, because of the
    // explicitly defaulted copy-constructor.
    {
        struct Foo {
            Foo() = default;
            Foo(Foo const&) = default;
            Foo(Foo&&) = default;
            hana::tuple<Trap4> t;
        };
    }
}