对于那些使用 C++17
的人来说,另一个选择是使用 折叠表达式。
template<typename T, typename ...Args>
constexpr typename std::enable_if_t<std::conjunction_v<std::is_same<T, Args>...>, std::optional<T>>
ToOneOf( typename std::underlying_type_t<T> value, Args&& ...args ) noexcept
{
static_assert( std::is_enum_v<T>, "'T' must be of type enum." );
using U = typename std::underlying_type_t<T>;
std::array<T, sizeof...( Args )> values{ std::forward<Args>( args )... };
const auto it{ std::find_if( std::cbegin( values ), std::cend( values ),
[ value ]( auto e ) { return static_cast<U>( e ) == value; } ) };
return it != std::end( values ) ? std::optional<T>{ *it } : std::nullopt;
}
template<typename T, typename ...Args>
constexpr typename std::enable_if_t<std::conjunction_v<std::is_same<T, Args>...>, bool>
IsOneOf( typename std::underlying_type_t<T> value, Args&& ...args ) noexcept
{
static_assert( std::is_enum_v<T>, "'T' must be of type enum." );
using U = typename std::underlying_type_t<T>;
return ( ... || ( value == static_cast<U>( args ) ) );
}
enum class Test
{
E0 = 12,
E1 = 56,
E2 = 101
};
int main( )
{
if ( IsOneOf<Test>( 12, Test::E0, Test::E1, Test::E2 ) )
{
std::cout << 12 << " is a valid enum value\n";
}
if ( auto opt{ ToOneOf<Test>( 56, Test::E0, Test::E1, Test::E2 ) } )
{
std::cout << static_cast<int>( opt.value( ) ) << " is a valid enum value\n";
}
}