我有一个模板函数,其中枚举类型转换为其基础类型,工作正常,但我写了一个重载应该采用整数并返回自身,它给我一个错误,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;
}
答案 0 :(得分:4)
std::underlying_type<TT>::type
正在std::enable_if
中进行评估,即使std::is_enum<TT>::value
为false
,因为false
不是错误。由于正在评估非枚举类型,因此导致错误。如果我们将SFINAE移动到模板参数中,我们可以获得所需的重载并仍然返回正确的类型。
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
中工作答案 1 :(得分:4)
尝试使用不属于枚举类型的std::underlying_type<T>
实例化T
,违反了标准对模板参数T
施加的要求:
§20.10.7.6[meta.trans.other] /表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
的{{1}}定义被请求std::enable_if<B,T>::type
}返回。