diff --git a/include/boost/endian/detail/is_fixed_enum.hpp b/include/boost/endian/detail/is_fixed_enum.hpp new file mode 100644 index 0000000..aae3bc8 --- /dev/null +++ b/include/boost/endian/detail/is_fixed_enum.hpp @@ -0,0 +1,51 @@ +#ifndef BOOST_ENDIAN_DETAIL_IS_FIXED_ENUM_HPP_INCLUDED +#define BOOST_ENDIAN_DETAIL_IS_FIXED_ENUM_HPP_INCLUDED + +// Copyright 2020 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +namespace boost +{ +namespace endian +{ +namespace detail +{ + +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) + +// Thanks to Will Wray for the T{0} idea, which unfortunately only works in C++17+ +// +// VS2017 works, VS2019 works from 19.20 to 19.22, then in 19.23 starts accepting +// T{0} for unscoped non-fixed enums as well. Sad! + +template struct is_fixed_enum_impl: boost::false_type +{ +}; + +template struct is_fixed_enum_impl: boost::is_enum +{ +}; + +template struct is_fixed_enum: is_fixed_enum_impl< boost::remove_cv_t > +{ +}; + +#else + +template struct is_fixed_enum: is_scoped_enum +{ +}; + +#endif + +} // namespace detail +} // namespace endian +} // namespace boost + +#endif // BOOST_ENDIAN_DETAIL_IS_FIXED_ENUM_HPP_INCLUDED diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fd71770..bb43116 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -98,3 +98,4 @@ run order_test.cpp ; run endian_reverse_test2.cpp ; run is_scoped_enum_test.cpp ; +run is_fixed_enum_test.cpp ; diff --git a/test/is_fixed_enum_test.cpp b/test/is_fixed_enum_test.cpp new file mode 100644 index 0000000..60131b9 --- /dev/null +++ b/test/is_fixed_enum_test.cpp @@ -0,0 +1,72 @@ +// Copyright 2020 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +enum E1 {}; + +#if !defined(BOOST_NO_CXX11_SCOPED_ENUMS) + +enum E2: long {}; +enum class E3 {}; +enum class E4: long {}; + +#endif + +struct X +{ + operator int() const { return 0; } +}; + +struct Y; + +template void test_true() +{ + using boost::endian::detail::is_fixed_enum; + + BOOST_TEST_TRAIT_TRUE((is_fixed_enum)); + BOOST_TEST_TRAIT_TRUE((is_fixed_enum)); + BOOST_TEST_TRAIT_TRUE((is_fixed_enum)); + BOOST_TEST_TRAIT_TRUE((is_fixed_enum)); +} + +template void test_false() +{ + using boost::endian::detail::is_fixed_enum; + + BOOST_TEST_TRAIT_FALSE((is_fixed_enum)); + BOOST_TEST_TRAIT_FALSE((is_fixed_enum)); + BOOST_TEST_TRAIT_FALSE((is_fixed_enum)); + BOOST_TEST_TRAIT_FALSE((is_fixed_enum)); +} + +int main() +{ + test_false(); + test_false(); + test_false(); + test_false(); + test_false(); + test_false(); + test_false(); + + test_false(); + +#if !defined(BOOST_NO_CXX11_SCOPED_ENUMS) + +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) + + test_true(); + +#endif + + test_true(); + test_true(); + +#endif + + return boost::report_errors(); +}