c++ - 如何使用 SFINAE 为枚举类中的缺失值制作 polyfill?

标签 c++ templates c++11 sfinae enum-class

我认为这应该很容易,但我已经为此苦苦挣扎了一段时间,所以我想我应该在这里问一下。

我想制作一个模板元函数,它采用对应于 C++11 枚举类的类型作为其参数,并返回一个 int:

  • 如果枚举类E有一个枚举值 a , 然后返回 static_cast<int>(E::a) .
  • 如果枚举类E没有枚举器值 a , 然后返回 42 .

然后我想制作一个模板函数,它采用某个枚举类的运行时实例 E , static 将其转换为 int,并检查它是否与此元函数匹配。

我尝试了很多次迭代,模板化结构并使用模板偏特化来尝试区分 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> header ,std::errc 有一堆枚举器值应该定义的,但是,在 mingw 上,其中一些丢失了。这会导致我的程序出现编译错误,因为这取决于如何 Asio已配置,lib::asio::errc可能类型定义为 std::errc , 和 websocketpp假设lib::asio::errc::operation_canceled是定义的符号。我想拼凑一些垫片,我可以把它放在 websocketpp 中。代码,以便它在任何平台上都可以接受地定义(如果存在,则定义为 lib::asio::errc::operation_canceled,如果不存在,则从 <cerrno> 定义为 ECANCELED。)

最佳答案

您可以通过多种方式做到这一点,其中之一是:

template <typename E, typename Enable = void>
struct get_a_int_val {
  static const int value = 42;
};

template <typename E>
struct get_a_int_val<E, typename std::enable_if<std::is_same<decltype(E::a), 
                                                decltype(E::a)>::value, void>::type>{
  static const int value = static_cast<int>(E::a);
};

LIVE DEMO

关于c++ - 如何使用 SFINAE 为枚举类中的缺失值制作 polyfill?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33679453/

相关文章:

c++ - 从基类的静态模板方法中调用继承类的 protected 构造函数失败

c++ - 非类型模板参数的类型抽象

c++ - begin() 和 end() 不应该只能针对类的左值引用调用吗?

c++ - 标准线程库与 Boost 相比如何?

c++ - 我的 seconds 变量没有正确存储

c++ - 与::函数语句混淆

c++ - 如何创建一次评估局部静态变量的静态方法?

c++ - 在编程 : Principles and Practice using C++ (Stroustrup) 的第 4 章中使用 "cin"钻 #7 获得不同的结果

c++ - Qt iOS 如何从可执行文件中排除资源以满足应用商店限制

c++ - glReadPixels 存储 x, y 值