I thought this should be easy, but I've been struggling with it for a while so I thought I should ask here.
I want to make a template metafunction that takes a type corresponding to a C++11 enum class as its argument, and returns an int:
- If the enum class
E
has an enumerator valuea
, then returnstatic_cast<int>(E::a)
. - If the enum class
E
does not have an enumerator valuea
, then return42
.
Then I would like to make a template function that takes a run-time instance of some enum class E
, static casts it to int, and checks if it matches this metafunction.
I tried many iterations of, templating a struct and use template partial specialization to try to distinguish if E::a
exists, also using function templates... I'm not sure if I can reconstruct everything that I tried but here's the most recent iteration:
template <typename E>
inline int get_a_int_val(int result = E::a) { return result; }
template <typename E>
inline int get_a_int_val(int result = 42) { return result; }
template <typename E>
inline bool is_a_val(const E & input) {
return static_cast<int>(input) == get_a_int_val<E>();
}
This doesn't work, because I'm redefining default arguments.
template <typename E, int result = E::a>
inline int get_a_int_val() { return result; }
template <typename E, int result = 42>
inline int get_a_int_val() { return result; }
template <typename E>
inline bool is_a_val(const E & input) {
return static_cast<int>(input) == get_a_int_val<E>();
}
This doesn't work, because non-type parameters cannot depend on type parameters.
template <typename E>
struct get_a_int_val {
static const int value = 42;
};
template <typename E>
struct get_a_int_val<E> {
static const int value = static_cast<int>(E::a);
};
template <typename E>
inline bool is_a_val(const E & input) {
return static_cast<int>(input) == get_a_int_val<E>::value;
}
This doesn't work, because
error:
class template partial specialization does not specialize any template
argument; to define the primary template, remove the template argument
list
What's the correct way to do this?
Motivation:
The reason that I want to do this is, I want to work around what seems to be a bug in libstdc++ which I reported here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68307
In C++11 in the <system_error>
header, there are a bunch of enumerator values for std::errc
which are supposed to be defined, however, on mingw some of them are missing. This causes compilation errors in my program because, depending on how Asio
is configured, lib::asio::errc
may be typedef'd to std::errc
, and websocketpp
assumes that lib::asio::errc::operation_canceled
is a defined symbol. I wanted to throw together some kind of shim that I can put around that in the websocketpp
code so that it will be defined acceptably on any platform (either to lib::asio::errc::operation_canceled
if it exists, or to ECANCELED from <cerrno>
if not.)