Added tests for scoped enums and underlying_type. Fixed a bug with native_value(). Fixed a bug that allowed implicit conversions of scoped enums to int (at least with clang 3.4).

This commit is contained in:
Andrey Semashev 2014-06-07 02:30:29 +04:00
parent 2b18ddfbce
commit f930ce31cf
6 changed files with 293 additions and 2 deletions

View File

@ -63,7 +63,7 @@ namespace boost
inline inline
typename EnumType::enum_type native_value(EnumType e) typename EnumType::enum_type native_value(EnumType e)
{ {
return e.native_value_(); return e.get_native_value_();
} }
#else // BOOST_NO_CXX11_SCOPED_ENUMS #else // BOOST_NO_CXX11_SCOPED_ENUMS
@ -126,7 +126,6 @@ namespace boost
#define BOOST_SCOPED_ENUM_DECLARE_END2() \ #define BOOST_SCOPED_ENUM_DECLARE_END2() \
enum_type get_native_value_() const BOOST_NOEXCEPT { return enum_type(v_); } \ enum_type get_native_value_() const BOOST_NOEXCEPT { return enum_type(v_); } \
operator enum_type() const BOOST_NOEXCEPT { return get_native_value_(); } \
friend bool operator ==(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)==enum_type(rhs.v_); } \ friend bool operator ==(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)==enum_type(rhs.v_); } \
friend bool operator ==(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)==rhs; } \ friend bool operator ==(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)==rhs; } \
friend bool operator ==(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs==enum_type(rhs.v_); } \ friend bool operator ==(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs==enum_type(rhs.v_); } \

View File

@ -75,3 +75,9 @@ run demangle_test.cpp : : : <test-info>always_show_run_output ;
run demangled_name_test.cpp : : : <test-info>always_show_run_output ; run demangled_name_test.cpp : : : <test-info>always_show_run_output ;
run demangled_name_test.cpp : : : <rtti>off <test-info>always_show_run_output : demangled_name_test_no_rtti ; run demangled_name_test.cpp : : : <rtti>off <test-info>always_show_run_output : demangled_name_test_no_rtti ;
run scoped_enum.cpp ;
compile-fail scoped_enum_compile_fail_conv_from_int.cpp ;
compile-fail scoped_enum_compile_fail_conv_to_int.cpp ;
run underlying_type.cpp ;

157
test/scoped_enum.cpp Normal file
View File

@ -0,0 +1,157 @@
/*
* 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>
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));
}
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();
}

View File

@ -0,0 +1,30 @@
/*
* 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_compile_fail_conv_from_int.cpp
* \author Andrey Semashev
* \date 06.06.2014
*
* \brief This test checks that scoped enum emulation prohibits implicit conversions from int
*/
#include <boost/core/scoped_enum.hpp>
BOOST_SCOPED_ENUM_DECLARE_BEGIN(color)
{
red,
green,
blue
}
BOOST_SCOPED_ENUM_DECLARE_END(color)
int main(int, char*[])
{
color col = 2;
return boost::native_value(col);
}

View File

@ -0,0 +1,31 @@
/*
* 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_compile_fail_conv_to_int.cpp
* \author Andrey Semashev
* \date 06.06.2014
*
* \brief This test checks that scoped enum emulation prohibits implicit conversions to int
*/
#include <boost/core/scoped_enum.hpp>
BOOST_SCOPED_ENUM_DECLARE_BEGIN(color)
{
red,
green,
blue
}
BOOST_SCOPED_ENUM_DECLARE_END(color)
int main(int, char*[])
{
color col = color::red;
int n = col;
return n;
}

68
test/underlying_type.cpp Normal file
View File

@ -0,0 +1,68 @@
/*
* 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 underlying_type.cpp
* \author Andrey Semashev
* \date 06.06.2014
*
* \brief This test checks that underlying_type trait works.
*/
#include <boost/core/underlying_type.hpp>
#include <boost/core/scoped_enum.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <boost/core/is_same.hpp>
#include <boost/config.hpp>
BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(emulated_enum, unsigned char)
{
value0,
value1,
value2
}
BOOST_SCOPED_ENUM_DECLARE_END(emulated_enum)
#if !defined(BOOST_NO_CXX11_SCOPED_ENUMS)
enum class native_enum : unsigned short
{
value0,
value1,
value2
};
#endif
#if defined(BOOST_NO_UNDERLYING_TYPE)
namespace boost {
template< >
struct underlying_type< emulated_enum >
{
typedef unsigned char type;
};
#if !defined(BOOST_NO_CXX11_SCOPED_ENUMS)
template< >
struct underlying_type< native_enum >
{
typedef unsigned short type;
};
#endif
} // namespace boost
#endif
int main(int, char*[])
{
BOOST_TEST_TRAIT_TRUE((boost::core::is_same< boost::underlying_type< emulated_enum >::type, unsigned char >));
#if !defined(BOOST_NO_CXX11_SCOPED_ENUMS)
BOOST_TEST_TRAIT_TRUE((boost::core::is_same< boost::underlying_type< native_enum >::type, unsigned short >));
#endif
return boost::report_errors();
}