C++ std::enable_if的约束变体及其问题

6

这是一个简短的问题,涉及到一个函数,我想返回一个enum class底层类型:

为什么这个版本可以正常工作?

template<typename T>
constexpr inline
typename std::enable_if_t<
  std::is_enum<T>::value,
  typename std::underlying_type_t<T>
>
enumValue(T p_rVal) noexcept
{
  return static_cast<typename std::underlying_type_t<T>>(p_rVal);
}

if (enumValue(myEnumClass) == 0) {}

而这个则会出现"未找到匹配的重载函数"错误(VS 2015):

template<
  typename T,
  typename std::enable_if_t<
    std::is_enum<T>::value,
    typename std::underlying_type_t<T>
  >
>
constexpr inline
typename std::underlying_type_t<T>
enumValue(T p_rVal) noexcept
{
  return static_cast<typename std::underlying_type_t<T>>(p_rVal);
}

非常感谢您的帮助!

@Dan,你为什么拒绝了Torbjörn提出的编辑建议?改善这篇文章的格式是非常有意义的。 - Walter
std::underlying_type_t<T>之前不需要使用typename - Oktalist
是的,没错,C++14的好处。我已经把它们移除了,不过还是谢谢你的提示! - gilgamash
1个回答

2
在您的第一个示例中,只有一个template参数T,在函数调用enumValue(myEnumClass)中从参数中推断出来。这是std::enable_if_t<>的正确用法。
在您的第二个示例中,有两个template参数,第一个可以再次被推导出来,但第二个不能。这是不适当/错误使用std::enable_if_t<>的方法。

啊!没错,我试了一下第二个版本,用了template <t = std::enable_if<...>>,结果运行良好!感谢你现在已被接受的答案! - gilgamash
1
是的,这里使用默认模板参数是最好的选择。它不会使函数签名混乱,并允许使用“auto”返回类型推断。 - Oktalist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接