File: scoped_enum.cpp

package info (click to toggle)
boost1.90 1.90.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 593,120 kB
  • sloc: cpp: 4,190,908; xml: 196,648; python: 34,618; ansic: 23,145; asm: 5,468; sh: 3,774; makefile: 1,161; perl: 1,020; sql: 728; ruby: 676; yacc: 478; java: 77; lisp: 24; csh: 6
file content (162 lines) | stat: -rw-r--r-- 3,914 bytes parent folder | download | duplicates (11)
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
160
161
162
/*
 *             Copyright Andrey Semashev 2014.
 * 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)
 */
/*!
 * \file   scoped_enum.cpp
 * \author Andrey Semashev
 * \date   06.06.2014
 *
 * \brief  This test checks that scoped enum emulation works similar to C++11 scoped enums.
 */

#include <boost/core/scoped_enum.hpp>
#include <boost/core/lightweight_test.hpp>

#if defined(_MSC_VER)
# pragma warning(disable: 4244) // conversion from enum_type to underlying_type
#endif

BOOST_SCOPED_ENUM_DECLARE_BEGIN(namespace_enum1)
{
    value0,
    value1,
    value2
}
BOOST_SCOPED_ENUM_DECLARE_END(namespace_enum1)

BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(namespace_enum2, unsigned char)
{
    // Checks that enum value names do not clash
    value0 = 10,
    value1 = 20,
    value2 = 30
}
BOOST_SCOPED_ENUM_DECLARE_END(namespace_enum2)

struct my_struct
{
    // Checks that declarations are valid in class scope
    BOOST_SCOPED_ENUM_DECLARE_BEGIN(color)
    {
        red,
        green,
        blue
    }
    BOOST_SCOPED_ENUM_DECLARE_END(color)

    color m_color;

    explicit my_struct(color col) : m_color(col)
    {
    }

    color get_color() const
    {
        return m_color;
    }
};

void check_operators()
{
    namespace_enum1 enum1 = namespace_enum1::value0;
    BOOST_TEST(enum1 == namespace_enum1::value0);
    BOOST_TEST(enum1 != namespace_enum1::value1);
    BOOST_TEST(enum1 != namespace_enum1::value2);

    enum1 = namespace_enum1::value1;
    BOOST_TEST(enum1 != namespace_enum1::value0);
    BOOST_TEST(enum1 == namespace_enum1::value1);
    BOOST_TEST(enum1 != namespace_enum1::value2);

    BOOST_TEST(!(enum1 < namespace_enum1::value0));
    BOOST_TEST(!(enum1 <= namespace_enum1::value0));
    BOOST_TEST(enum1 >= namespace_enum1::value0);
    BOOST_TEST(enum1 > namespace_enum1::value0);

    BOOST_TEST(!(enum1 < namespace_enum1::value1));
    BOOST_TEST(enum1 <= namespace_enum1::value1);
    BOOST_TEST(enum1 >= namespace_enum1::value1);
    BOOST_TEST(!(enum1 > namespace_enum1::value1));

    namespace_enum1 enum2 = namespace_enum1::value0;
    BOOST_TEST(enum1 != enum2);

    enum2 = enum1;
    BOOST_TEST(enum1 == enum2);
}

void check_argument_passing()
{
    my_struct str(my_struct::color::green);
    BOOST_TEST(str.get_color() == my_struct::color::green);
}

void check_switch_case()
{
    my_struct str(my_struct::color::blue);

    switch (boost::native_value(str.get_color()))
    {
    case my_struct::color::blue:
        break;
    default:
        BOOST_ERROR("Unexpected color value in switch/case");
    }
}

template< typename T >
struct my_trait
{
    enum _ { value = 0 };
};

template< >
struct my_trait< BOOST_SCOPED_ENUM_NATIVE(namespace_enum2) >
{
    enum _ { value = 1 };
};

template< typename T >
void native_type_helper(T)
{
    BOOST_TEST(my_trait< T >::value != 0);
}

void check_native_type()
{
    BOOST_TEST(my_trait< int >::value == 0);
    BOOST_TEST(my_trait< BOOST_SCOPED_ENUM_NATIVE(namespace_enum2) >::value != 0);
    BOOST_TEST(my_trait< boost::native_type< namespace_enum2 >::type >::value != 0);

    namespace_enum2 enum1 = namespace_enum2::value0;
    native_type_helper(boost::native_value(enum1));
}

void check_underlying_cast()
{
    namespace_enum2 enum1 = namespace_enum2::value1;
    BOOST_TEST(boost::underlying_cast< unsigned char >(enum1) == 20);
}

void check_underlying_type()
{
    // The real check for the type is in the underlying_type trait test.
    namespace_enum2 enum1 = namespace_enum2::value1;
    BOOST_TEST(sizeof(enum1) == sizeof(unsigned char));
    (void)enum1;
}

int main(int, char*[])
{
    check_operators();
    check_argument_passing();
    check_switch_case();
    check_native_type();
    check_underlying_cast();
    check_underlying_type();

    return boost::report_errors();
}