"Conversion" 从类型到相同类型导致错误

"Conversion" from type to same type is causing error

我有一个模板函数,其中枚举类型转换为它的底层类型,工作正常,但我写了一个重载,它应该采用整数和 return 本身,它给我一个 int 错误不是枚举类型。在我的模板中,这应该已经被过滤掉了。怎么了?

模板代码如下:

  template <typename TT>
  static constexpr auto get_value(TT t)
    -> typename std::enable_if<!std::is_enum<TT>::value, TT>::type
    {
      return t;
    }

  template <typename TT>
  static constexpr auto get_value(TT t)
    -> typename std::enable_if<std::is_enum<TT>::value, typename std::underlying_type<TT>::type>::type
    {
      return (typename std::underlying_type<TT>::type)t;
    }

Demo

std::underlying_type<TT>::type 正在 std::enable_if 中计算,即使 std::is_enum<TT>::valuefalse,因为 false 不是错误。由于正在评估非枚举类型,因此它会导致错误。如果我们将 SFINAE 移动到模板参数中,我们可以获得所需的重载并且仍然 return 正确的类型。

template <typename TT, typename std::enable_if<!std::is_enum<TT>::value, TT>::type* = nullptr>
static constexpr auto get_value(TT t) -> TT
{
    return t;
}

template <typename TT, typename std::enable_if<std::is_enum<TT>::value>::type* = nullptr>
static constexpr auto get_value(TT t) -> typename std::underlying_type<TT>::type
{
    return (typename std::underlying_type<TT>::type)t;
}

你可以看到它在这个 Live Example

中工作

通过尝试使用非枚举类型的 T 实例化 std::underlying_type<T>,您违反了标准对模板参数 T:

的要求

§ 20.10.7.6 [meta.trans.other]/Table 57:

       Template         |         Condition         |       Comments
------------------------+---------------------------+-----------------------
template <class T>      | T shall be an enumeration | The member typedef
struct underlying_type; | type (7.2)                | type shall name
                        |                           | the underlying type 
                        |                           | of T.

如果不喜欢任何额外的模板参数,这里有另一种方法:

template <typename TT>
static constexpr auto get_value(TT t)
    -> typename std::enable_if<!std::is_enum<TT>::value, TT>::type
{
    return t;
}

template <typename TT>
static constexpr auto get_value(TT t)
    -> typename std::enable_if<std::is_enum<TT>::value
                             , std::underlying_type<TT>
                >::type::type
{
    return (typename std::underlying_type<TT>::type)t;
}

这样,std::underlying_type<TT> 的实例化被推迟到 std::enable_if 中的条件计算为 true,因为嵌套的 type 定义被请求用于 std::enable_if<B,T>::type returns.

DEMO