mirror of
https://github.com/aantron/better-enums.git
synced 2025-12-06 16:56:42 +08:00
With this change, the underlying type can be a non-integral type that provides conversions to and from an integral type. See the test at test/cxxtest/underlying.h for some examples - though they are more verbose than strictly necessary, for testing needs. Move constructors in underlying types are not supported. It has been difficult so far to get constexpr code not to select the move constructor, which is generally not constexpr, for various operations.
155 lines
4.7 KiB
C++
155 lines
4.7 KiB
C++
#include <cxxtest/TestSuite.h>
|
|
#include <enum.h>
|
|
|
|
// This test uses internal constants declared by feature testing macros in
|
|
// enum.h. They are not part of the public interface, but are used here to avoid
|
|
// duplication of definitions for C++11 and C++98.
|
|
//
|
|
// BETTER_ENUMS__CONSTEXPR is a synonym for constexpr when available, and
|
|
// othewise expands to nothing.
|
|
|
|
|
|
|
|
// Using a type trait.
|
|
struct html_color_1 {
|
|
unsigned char r, g, b;
|
|
|
|
BETTER_ENUMS__CONSTEXPR
|
|
html_color_1(unsigned char _r, unsigned char _g, unsigned char _b) :
|
|
r(_r), g(_g), b(_b) { }
|
|
};
|
|
|
|
// In C++11, can simply to struct ::better_enums::underlying_traits below.
|
|
namespace better_enums {
|
|
|
|
template <>
|
|
struct underlying_traits<html_color_1> {
|
|
typedef unsigned int integral_representation;
|
|
|
|
BETTER_ENUMS__CONSTEXPR static html_color_1 from_integral(unsigned int i)
|
|
{ return html_color_1(i >> 16 & 0xff, i >> 8 & 0xff, i & 0xff); }
|
|
|
|
BETTER_ENUMS__CONSTEXPR static unsigned int to_integral(html_color_1 v)
|
|
{ return (unsigned int)v.r << 16 | (unsigned int)v.g << 8 | v.b; }
|
|
|
|
BETTER_ENUMS__CONSTEXPR static bool
|
|
are_equal(const html_color_1 &u, const html_color_1 &v)
|
|
{ return u.r == v.r && u.g == v.g && u.b == v.b; }
|
|
};
|
|
|
|
}
|
|
|
|
ENUM(HtmlColor1, html_color_1,
|
|
darksalmon = 0xc47451, purplemimosa = 0x9e7bff, slimegreen = 0xbce954)
|
|
|
|
|
|
|
|
// Using member definitions.
|
|
struct html_color_2 {
|
|
unsigned char r, g, b;
|
|
|
|
BETTER_ENUMS__CONSTEXPR
|
|
html_color_2(unsigned char _r, unsigned char _g, unsigned char _b) :
|
|
r(_r), g(_g), b(_b) { }
|
|
|
|
|
|
|
|
typedef unsigned int integral_representation;
|
|
|
|
explicit BETTER_ENUMS__CONSTEXPR html_color_2(unsigned int i) :
|
|
r(i >> 16 & 0xff), g(i >> 8 & 0xff), b(i & 0xff) { }
|
|
|
|
BETTER_ENUMS__CONSTEXPR operator unsigned int() const
|
|
{ return (unsigned int)r << 16 | (unsigned int)g << 8 | b; }
|
|
};
|
|
|
|
// Initializers are not supported before GCC 5.1, even with a literal type and
|
|
// constexpr conversion to integer.
|
|
#ifdef BETTER_ENUMS__HAVE_CONSTEXPR
|
|
# ifdef __GNUC__
|
|
# ifdef __clang__
|
|
# define SUPPORT_INITIALIZER
|
|
# else
|
|
# if __GNUC__ >= 5
|
|
# define SUPPORT_INITIALIZER
|
|
# endif
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef SUPPORT_INITIALIZER
|
|
ENUM(HtmlColor2, html_color_2,
|
|
darksalmon = 0xc47451, purplemimosa = 0x9e7bff, slimegreen = 0xbce954,
|
|
celeste = html_color_2(0x50, 0xeb, 0xec))
|
|
#else
|
|
ENUM(HtmlColor2, html_color_2,
|
|
darksalmon = 0xc47451, purplemimosa = 0x9e7bff, slimegreen = 0xbce954)
|
|
#endif
|
|
|
|
|
|
|
|
class UnderlyingTypeTests : public CxxTest::TestSuite {
|
|
public:
|
|
void test_basics_and_operators()
|
|
{
|
|
HtmlColor1 color_1 = HtmlColor1::darksalmon;
|
|
|
|
TS_ASSERT_EQUALS(color_1->r, 0xc4);
|
|
TS_ASSERT_EQUALS(color_1->g, 0x74);
|
|
TS_ASSERT_EQUALS(color_1->b, 0x51);
|
|
|
|
TS_ASSERT_EQUALS(sizeof(HtmlColor1), sizeof(html_color_1));
|
|
|
|
HtmlColor2 color_2 = HtmlColor2::purplemimosa;
|
|
|
|
TS_ASSERT_EQUALS(color_2->r, 0x9e);
|
|
TS_ASSERT_EQUALS(color_2->g, 0x7b);
|
|
TS_ASSERT_EQUALS(color_2->b, 0xff);
|
|
|
|
TS_ASSERT_EQUALS(sizeof(HtmlColor2), sizeof(html_color_2));
|
|
|
|
#ifdef SUPPORT_INITIALIZER
|
|
HtmlColor2 color_3 = HtmlColor2::celeste;
|
|
|
|
TS_ASSERT_EQUALS(color_3->r, 0x50);
|
|
TS_ASSERT_EQUALS(color_3->g, 0xeb);
|
|
TS_ASSERT_EQUALS(color_3->b, 0xec);
|
|
#endif
|
|
|
|
color_1->r = 0;
|
|
|
|
const HtmlColor1 const_color = HtmlColor1::slimegreen;
|
|
TS_ASSERT_EQUALS(const_color->r, 0xbc);
|
|
|
|
html_color_1 &color_1_reference = *color_1;
|
|
const html_color_1 &const_color_reference = *const_color;
|
|
|
|
TS_ASSERT_EQUALS(color_1_reference.r, 0);
|
|
TS_ASSERT_EQUALS(const_color_reference.r, 0xbc);
|
|
}
|
|
|
|
void test_conversion_functions()
|
|
{
|
|
HtmlColor2 color_1 = HtmlColor2::darksalmon;
|
|
html_color_2 color_1_underlying = color_1._to_underlying();
|
|
|
|
TS_ASSERT_EQUALS(color_1_underlying.r, color_1->r);
|
|
TS_ASSERT_EQUALS(color_1_underlying.g, color_1->g);
|
|
TS_ASSERT_EQUALS(color_1_underlying.b, color_1->b);
|
|
|
|
color_1_underlying = html_color_2(HtmlColor2::slimegreen);
|
|
color_1 = HtmlColor2::_from_underlying(color_1_underlying);
|
|
|
|
TS_ASSERT_EQUALS(color_1->r, color_1_underlying.r);
|
|
TS_ASSERT_EQUALS(color_1->g, color_1_underlying.g);
|
|
TS_ASSERT_EQUALS(color_1->b, color_1_underlying.b);
|
|
|
|
color_1_underlying = html_color_2(1, 2, 3);
|
|
color_1 = HtmlColor2::_from_underlying_unchecked(color_1_underlying);
|
|
|
|
TS_ASSERT_EQUALS(color_1->r, color_1_underlying.r);
|
|
TS_ASSERT_EQUALS(color_1->g, color_1_underlying.g);
|
|
TS_ASSERT_EQUALS(color_1->b, color_1_underlying.b);
|
|
}
|
|
};
|