I thought this fine as it compiles on Visual Studio, but I found out when trying to compile on GCC and Clang that it might not be kosher:
#include <iostream>
#include <type_traits>
struct Bitfield
{
template <typename first_arg_type, typename ... other_arg_types>
static constexpr first_arg_type orTogether(first_arg_type firstArg, other_arg_types&& ... otherArgs)
{
if constexpr (std::is_enum_v<first_arg_type>)
{
using underlying_type = std::underlying_type_t<first_arg_type>;
underlying_type result = static_cast<underlying_type>(firstArg);
// Or with the rest
((result |= static_cast<underlying_type>(otherArgs)), ...);
return static_cast<first_arg_type>(result);
}
else if constexpr (std::is_integral_v<first_arg_type>)
{
first_arg_type result = firstArg;
// Or with the rest
((result |= otherArgs), ...);
return result;
}
else {static_assert(false, "types must be either enum or integral");}
}
};
int main()
{
}
The static_assert fires. The interesting thing is that it's not even instantiated. You can see on Godbolt that it compiles only on Visual Studio.