std::enable_if:参数与模板参数
std::enable_if : parameter vs template parameter
我正在构建一些输入检查器,该检查器需要具有整数和/或双精度的特定函数(例如"isPrime"应该仅适用于整数)。
如果我使用 enable_if
作为参数,它运行良好:
template <class T>
class check
{
public:
template< class U = T>
inline static U readVal(typename std::enable_if<std::is_same<U, int>::value >::type* = 0)
{
return BuffCheck.getInt();
}
template< class U = T>
inline static U readVal(typename std::enable_if<std::is_same<U, double>::value >::type* = 0)
{
return BuffCheck.getDouble();
}
};
但是如果我将其用作模板参数(如 http://en.cppreference.com/w/cpp/types/enable_if 所示)
template <class T>
class check
{
public:
template< class U = T, class = typename std::enable_if<std::is_same<U, int>::value>::type >
inline static U readVal()
{
return BuffCheck.getInt();
}
template< class U = T, class = typename std::enable_if<std::is_same<U, double>::value>::type >
inline static U readVal()
{
return BuffCheck.getDouble();
}
};
然后我有以下错误:
error: ‘template<class T> template<class U, class> static U check::readVal()’ cannot be overloaded
error: with ‘template<class T> template<class U, class> static U check::readVal()’
我无法弄清楚第二个版本中出了什么问题。
默认模板参数不是模板签名的一部分(因此两个定义都尝试定义同一模板两次)。但是,它们的参数类型是签名的一部分。所以你可以做
template <class T>
class check
{
public:
template< class U = T,
typename std::enable_if<std::is_same<U, int>::value, int>::type = 0>
inline static U readVal()
{
return BuffCheck.getInt();
}
template< class U = T,
typename std::enable_if<std::is_same<U, double>::value, int>::type = 0>
inline static U readVal()
{
return BuffCheck.getDouble();
}
};
问题是编译器看到同一方法的 2 个重载,这两个重载都包含相同的参数(在本例中为 none)和相同的返回值。您无法提供此类定义。最干净的方法是在函数的返回值上使用 SFINAE:
template <class T>
class check
{
public:
template< class U = T>
static typename std::enable_if<std::is_same<U, int>::value, U>::type readVal()
{
return BuffCheck.getInt();
}
template< class U = T>
static typename std::enable_if<std::is_same<U, double>::value, U>::type readVal()
{
return BuffCheck.getDouble();
}
};
这样,您就可以提供 2 种不同的重载。一个返回一个 int,另一个返回一个双精度,并且只有一个可以使用某个 T 实例化。
我知道
这个问题是关于std::enable_if
的,但是,我喜欢提供一种替代解决方案来解决相同的问题而无需enable_if。它确实需要C++17
template <class T>
class check
{
public:
inline static T readVal()
{
if constexpr (std::is_same_v<T, int>)
return BuffCheck.getInt();
else if constexpr (std::is_same_v<T, double>)
return BuffCheck.getDouble();
}
};
这段代码看起来更像是在运行时编写的。所有分支都必须语法正确,但语义不必正确。在这种情况下,如果 T 是 int,getDouble 不会导致编译错误(或警告),因为它不会被编译器检查/使用。
如果函数的返回类型很复杂,则始终可以使用auto
作为返回类型。
相关文章:
- 如何将enable-if与模板参数和参数包一起使用
- 将 out/in out 参数与 if/switch 的 init 语句一起使用
- MSVC使用constexpr-if从可变模板方法中的基本模板参数中吞下const
- 在if constexpr中使用带参数包的概念时,升级到gcc 9后出现编译错误
- clang 格式堆叠所有 if 语句参数,如果它们太长
- 在 constexpr-if 条件下比较 constexpr 函数参数会导致错误
- 在通用 lambda 中使用 constexpr-if 来确定参数的类型
- "if (argc < 2 || argc > 2)"应该有 2 个参数吗?&终止在抛出'std::out_of_range'错误实例后调用
- 是否可以使用模板非类型参数使用#if指令?(矢量多合一类)
- 递归可变参数函数调用对简单 if.else 语句的性能
- 是否有等效的 #if 可以评估模板参数
- 我可以在 if 语句中使用"x=2"作为参数吗?
- 为什么if语句中未定义的参数不会导致segfault或其他错误
- 如何启动具有许多布尔参数的函数模板,而不使用 2^n if 语句
- 函数参数内的If语句;分支类型
- "IF"参数评估顺序?
- 隐藏c++参数的有趣案例(参数没有在if块中隐藏)
- 考虑到模板参数,正在更改if语句条件
- QT5迁移和Boost:if.hp:宏参数不匹配错误
- 如何使用在C++中具有多个参数的if语句来调用多个函数