Reputation: 95
I'm trying to write a generic template overload for the bitswise << operator, but I'm having a hard time specifying that the left side of the operator is an enum, and the compiler gives me an 'ambiguous overload' error.
I'd hope that the static_assert would tell the compiler that the << operator in "file << x" is not the template I've defined, and it would then pick up the << operator defined in iostream. But, I get a compiler message saying that the two are ambiguous.
It does not have this issue with "cout << x".
#include <fstream>
#include <iostream>
using namespace std;
enum DAY{MON=1,TUES=2,WED=4,THUR=8,FRI=16};
template<typename Enum>
constexpr Enum operator <<(Enum e,int n)
{
static_assert(std::is_enum<Enum>::value,
"template parameter is not an enum type");
using underlying = typename std::underlying_type<Enum>::type;
return static_cast<Enum> ( static_cast<underlying>(e) << n );
}
int main()
{
// this does as I'd like
DAY day = MON;
day = static_cast<DAY>(day << 2); // this is the behavior I need
cout << day << endl;
// but this is ambiguous
ofstream file("test.dat");
float x;
file << x; // this line is ambigous
return 0;
}
Upvotes: 0
Views: 366
Reputation: 30494
static_assert
applies too late to remove your operator<<
from overload resolution. You need to use SFINAE instead. Something like this will do what you want:
template <typename Enum>
constexpr std::enable_if_t<std::is_enum_v<Enum>, Enum>
operator<<(Enum e, int n)
{
using underlying = typename std::underlying_type_t<Enum>;
return static_cast<Enum> ( static_cast<underlying>(e) << n );
}
Upvotes: 3