Я думал, что это должно быть легко, но я боролся с ним какое-то время, поэтому я подумал, что я должен спросить здесь.Как использовать SFINAE для создания полиполнения для отсутствующих значений в классе enum?
Я хочу сделать шаблон metafunction, который принимает тип, соответствующий C++ 11 класса в перечислениях в качестве аргумента и возвращает INT:
- Если класс перечисления
E
имеет значение перечислителяa
, затем вернитеstatic_cast<int>(E::a)
. - Если класс перечисления
E
не имеет значения перечислителяa
, тогда возвращается42
.
Тогда я хотел бы сделать шаблонную функцию, которая принимает во время выполнения экземпляра некоторого перечислимого класса E
, статические отбрасывает его в целое, и проверяет, если он соответствует этому metafunction.
Я пробовал много итераций, шаблонов структуры и использования шаблона частичной специализации, чтобы попытаться отличить, если E::a
существует, также используя шаблоны функций ... Я не уверен, могу ли я восстановить все, что я пробовал, но вот самое недавняя итерация:
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>();
}
Это не работает, потому что я переопределяю аргументы по умолчанию.
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>();
}
Это не работает, поскольку параметры непигового типа не могут зависеть от параметров типа.
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;
}
Это не работает, потому что
error:
class template partial specialization does not specialize any template
argument; to define the primary template, remove the template argument
list
Что такое правильный способ сделать это?
Мотивация:
Причина, по которой я хочу сделать это, я хочу работать вокруг того, что, кажется, ошибка в libstdC++, который я сообщил здесь: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68307
В C++ 11 в заголовке <system_error>
, существует пучка значений перечислителя для std::errc
, которые должны быть определены, однако, при воспроизведении некоторых из них не хватает. Это вызывает ошибки компиляции в моей программе, потому что, в зависимости от того, как настроено Asio
, lib::asio::errc
может быть typedef'd до std::errc
, а websocketpp
предполагает, что lib::asio::errc::operation_canceled
является определенным символом. Я хотел скомпоновать какую-то прокладку, которую я могу использовать в коде websocketpp
, чтобы он был определен приемлемо на любой платформе (либо до lib::asio::errc::operation_canceled
, если он существует, либо в ECANCELED от <cerrno>
, если нет.)