[英]std::enable_if : parameter vs template parameter
I'm building some input checker that needs to have specific functions for integer and/or double (for example 'isPrime' should only be available for integers).我正在构建一些输入检查器,它需要具有整数和/或双精度的特定函数(例如,'isPrime' 应该只适用于整数)。
If I'm using enable_if
as a parameter it's working perfectly :如果我使用
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();
}
};
but if I'm using it as a template paramater (as demonstrated on http://en.cppreference.com/w/cpp/types/enable_if )但如果我将它用作模板参数(如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();
}
};
then I have the following error :然后我有以下错误:
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()’
I can't figure out what is wrong in the second version.我无法弄清楚第二个版本有什么问题。
Default template arguments are not part of the signature of a template (so both definitions try to define the same template twice).默认模板参数不是模板签名的一部分(因此两个定义都尝试定义相同的模板两次)。 Their parameter types are part of the signature, however.
然而,它们的参数类型是签名的一部分。 So you can do
所以你可以做
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();
}
};
The problem is that the compiler sees 2 overloads of the same method, both which contain the same arguments(none, in this case) and the same return value.问题是编译器看到同一个方法的 2 个重载,它们都包含相同的参数(在这种情况下没有)和相同的返回值。 You can't provide such definition.
你不能提供这样的定义。 The cleanest way to do this is to use SFINAE on the function's return value:
最简洁的方法是在函数的返回值上使用 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();
}
};
That way, you're providing 2 different overloads.这样,您就提供了 2 种不同的重载。 One returns an int, the other one returns a double, and only one can be instantiated using a certain T.
一个返回一个int,另一个返回一个double,并且只有一个可以使用某个T来实例化。
I know this question is about std::enable_if
, however, I like to provide an alternative solution to solve the same problem without enable_if.我知道这个问题是关于
std::enable_if
,但是,我喜欢提供一种替代解决方案来解决没有 enable_if 的相同问题。 It does require C++17它确实需要 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();
}
};
This code looks more as if you would write it at runtime.这段代码看起来更像是在运行时编写的。 All branches have to be syntactic correct, however the semantics don't have to be.
所有分支都必须在句法上正确,但语义不必如此。 In this case, if T is int, the getDouble ain't causing compilation errors (or warnings) as it doesn't get checked/used by the compiler.
在这种情况下,如果 T 是 int,则 getDouble 不会导致编译错误(或警告),因为它不会被编译器检查/使用。
If the return type of the function would be to complex to mention, you can always use auto
as the return type.如果函数的返回类型很复杂,您可以始终使用
auto
作为返回类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.