summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/variant/test/variant_multivisit_test.cpp
blob: 06945239883299f4f33ba8feee92436cf7f7dfee (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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//-----------------------------------------------------------------------------
// boost-libs variant/test/variant_multivisit_test.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2013-2020 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#include "boost/config.hpp"
#include "boost/noncopyable.hpp"
#define BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS 5
#include "boost/variant/multivisitors.hpp"
#include "boost/variant.hpp"

#include "boost/core/lightweight_test.hpp"

struct my_noncopyable : boost::noncopyable {
    my_noncopyable(){}
    ~my_noncopyable(){}
};

typedef boost::variant<my_noncopyable, int>         variant_noncopy_t;


typedef boost::variant<char, unsigned char, signed char, unsigned short, int, unsigned int>         variant6_t;

struct test_visitor: boost::static_visitor<> {
    // operators that shall not be called
    template <class  T1, class  T2, class  T3>
    void operator()(T1&, T2&, T3&) const 
    {
        BOOST_TEST(false);
    }

    template <class  T1, class  T2, class  T3, class  T4>
    void operator()(T1&, T2&, T3&, T4&) const 
    {
        BOOST_TEST(false);
    }

    template <class  T1, class  T2, class  T3, class  T4, class  T5>
    void operator()(T1&, T2&, T3&, T4&, T5&) const 
    {
        BOOST_TEST(false);
    }

    // operators that are OK to call
    void operator()(char v0, unsigned char v1, signed char v2) const 
    {
        BOOST_TEST(v0 == 0);
        BOOST_TEST(v1 == 1);
        BOOST_TEST(v2 == 2);
    }

    void operator()(char v0, unsigned char v1, signed char v2, unsigned short v3) const 
    {
        BOOST_TEST(v0 == 0);
        BOOST_TEST(v1 == 1);
        BOOST_TEST(v2 == 2);
        BOOST_TEST(v3 == 3);
    }

    void operator()(char v0, unsigned char v1, signed char v2, unsigned short v3, int v4) const 
    {
        BOOST_TEST(v0 == 0);
        BOOST_TEST(v1 == 1);
        BOOST_TEST(v2 == 2);
        BOOST_TEST(v3 == 3);
        BOOST_TEST(v4 == 4);
    }


    // Noncopyables
    void operator()(my_noncopyable&, my_noncopyable&, my_noncopyable&) const {
        BOOST_TEST(true);
    }
    void operator()(my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&) const {
        BOOST_TEST(true);
    }
    void operator()(my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&) const {
        BOOST_TEST(true);
    }
    void operator()(my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&) const {
        BOOST_TEST(true);
    }
};

typedef boost::variant<int, double, bool> bool_like_t;
typedef boost::variant<int, double> arithmetics_t;

struct if_visitor: public boost::static_visitor<arithmetics_t> {
    template <class T0, class T1, class T2>
    arithmetics_t operator()(T0 b, T1 v1, T2 v2) const {
        if (!!b) {
            return v1;
        } else {
            return v2;
        }
    }
};


int main()
{
    test_visitor v;

    variant6_t v_array6[6];
    v_array6[0] = char(0);
    v_array6[1] = static_cast<unsigned char>(1);
    v_array6[2] = static_cast<signed char>(2);
    v_array6[3] = static_cast<unsigned short>(3);
    v_array6[4] = static_cast<int>(4);
    v_array6[5] = static_cast<unsigned int>(5);

    boost::apply_visitor(v, v_array6[0], v_array6[1], v_array6[2]);
    boost::apply_visitor(test_visitor(), v_array6[0], v_array6[1], v_array6[2]);

// Following test also pass, but requires many Gigabytes of RAM for compilation and compile for about 15 minutes
//#define BOOST_VARIANT_MULTIVISITORS_TEST_VERY_EXTREME
#ifdef BOOST_VARIANT_MULTIVISITORS_TEST_VERY_EXTREME    
    boost::apply_visitor(v, v_array6[0], v_array6[1], v_array6[2], v_array6[3]);
    boost::apply_visitor(test_visitor(), v_array6[0], v_array6[1], v_array6[2], v_array6[3]);

    boost::apply_visitor(v, v_array6[0], v_array6[1], v_array6[2], v_array6[3], v_array6[4]);
    boost::apply_visitor(test_visitor(), v_array6[0], v_array6[1], v_array6[2], v_array6[3], v_array6[4]);
#endif

    bool_like_t v0(1), v1(true), v2(1.0);

    BOOST_TEST(
        boost::apply_visitor(if_visitor(), v0, v1, v2)
        ==
        arithmetics_t(true)
    );

#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
    if_visitor if_vis;
    BOOST_TEST(
        boost::apply_visitor(if_vis)(v0, v1, v2)
        ==
        arithmetics_t(true)
    );
#endif


    variant_noncopy_t vnonc[6];
    boost::apply_visitor(v, vnonc[0], vnonc[1], vnonc[2]);
    boost::apply_visitor(test_visitor(), vnonc[0], vnonc[1], vnonc[2], vnonc[3]);

#ifdef BOOST_VARIANT_MULTIVISITORS_TEST_VERY_EXTREME
    boost::apply_visitor(v, vnonc[0], vnonc[1], vnonc[2], vnonc[3], vnonc[4]);
    boost::apply_visitor(test_visitor(), vnonc[0], vnonc[1], vnonc[2], vnonc[3], vnonc[4], vnonc[5]);
#endif

    return boost::report_errors();
}