模板专门化和enable_if问题 [英] Template specialization and enable_if problems
问题描述
我遇到了关于适当使用enable_if和模板专用化的问题。
修改示例后(出于保密原因),这里有一个类似的示例: / p>
我有一个名为less的函数,用于检查第一个arg小于第二个
arg。让我们说,我想有2种不同的实现
取决于输入的类型-1整数的实现和
的另一个double。
我到目前为止的代码看起来像这样 -
#include< type_traits>
#include< iostream>
template< class T,
class = typename std :: enable_if< std :: is_floating_point< T> :: value> :: type&
bool less(T a,T b){
// ...
}
模板< class T,
class = typename std :: enable_if< std :: is_integral< T> :: value> :: type>
bool less(T a,T b){
// ...
}
int main(){
float a;
float b;
less(a,b);
return 0;
}
上述代码不能编译,因为它说我重新定义
错误是:
Z.cpp: 15:19:error:template parameter redefines default argument
class = typename std :: enable_if< std :: is_integral< T> :: value> :: type>
^
Z.cpp:9:19:注意:之前定义的默认模板参数
class = typename std :: enable_if< std :: is_floating_point< T> value> :: type>
^
Z.cpp:16:11:error:redefinition of'less'
bool less(T a,T b){
^
Z.cpp:10:11:注意:以前的定义在这里
bool less(T a,T b){
^
Z.cpp: 23:5:错误:没有匹配函数调用'less'
less(a,b);
^ ~~~
Z.cpp:15:43:注意:候选模板被忽略:被'enable_if'禁用
[with T = float]
= typename std :: enable_if< std :: is_integral< T> :: value> :: type>
^
生成3个错误。有人可以指出这里的错误是什么?
h2_lin>解决方案
默认模板参数不是函数模板签名的一部分。所以在你的例子中,你有两个相同的重载少
,这是非法的。 clang抱怨缺省参数的重新定义(根据§14.1/ 12 [temp.param],这是非法的),而gcc产生以下错误消息:
错误:redefinition'
模板< class T,class> bool less(T,T)
'
要修复错误,请移动 enable_if
从默认参数到虚拟模板参数的表达式
模板< class T,
typename std :: enable_if< std :: is_floating_point< T> :: value,int> :: type * = nullptr>
bool less(T a,T b){
// ...
}
模板< class T,
typename std: :enable_if< std :: is_integral< T> :: value,int> :: type * = nullptr>
bool less(T a,T b){
// ....
}
另一种选择是在返回类型中使用 enable_if
,虽然我觉得这更难阅读。
模板< class T>
typename std :: enable_if< std :: is_floating_point< T> :: value,bool> :: type
less(T a,T b){
// ....
}
template< class T>
typename std :: enable_if< std :: is_integral< T> :: value,bool> :: type
less(T a,T b){
// ....
}
I am running into a problem regarding the appropriate usage of enable_if and template specialization.
After modifying the example (for confidentiality reasons), here's a comparable example:
I have function called "less" that checks if 1st arg is less than 2nd arg. Let's say I want to have 2 different kinds of implementations depending on the type of input - 1 implementation for integer and another for double.
The code that I have so far looks like this -
#include <type_traits>
#include <iostream>
template <class T,
class = typename std::enable_if<std::is_floating_point<T>::value>::type>
bool less(T a, T b) {
// ....
}
template <class T,
class = typename std::enable_if<std::is_integral<T>::value>::type>
bool less(T a, T b) {
// ....
}
int main() {
float a;
float b;
less(a,b);
return 0;
}
The above code does not compile because - It says that I am re-defining the less method.
Errors are:
Z.cpp:15:19: error: template parameter redefines default argument
class = typename std::enable_if<std::is_integral<T>::value>::type>
^
Z.cpp:9:19: note: previous default template argument defined here
class = typename std::enable_if<std::is_floating_point<T>::value>::type>
^
Z.cpp:16:11: error: redefinition of 'less'
bool less(T a, T b) {
^
Z.cpp:10:11: note: previous definition is here
bool less(T a, T b) {
^
Z.cpp:23:5: error: no matching function for call to 'less'
less(a,b);
^~~~
Z.cpp:15:43: note: candidate template ignored: disabled by 'enable_if'
[with T = float]
class = typename std::enable_if<std::is_integral<T>::value>::type>
^
3 errors generated.
Can someone point out what's the mistake here?
Default template arguments are not part of the signature of a function template. So in your example you have two identical overloads of less
, which is illegal. clang complains about the redefinition of the default argument (which is also illegal according to §14.1/12 [temp.param]), while gcc produces the following error message:
error: redefinition of '
template<class T, class> bool less(T, T)
'
To fix the error move the enable_if
expression from default argument to a dummy template parameter
template <class T,
typename std::enable_if<std::is_floating_point<T>::value, int>::type* = nullptr>
bool less(T a, T b) {
// ....
}
template <class T,
typename std::enable_if<std::is_integral<T>::value, int>::type* = nullptr>
bool less(T a, T b) {
// ....
}
Another option is to use enable_if
in the return type, though I feel this is harder to read.
template <class T>
typename std::enable_if<std::is_floating_point<T>::value, bool>::type
less(T a, T b) {
// ....
}
template <class T>
typename std::enable_if<std::is_integral<T>::value, bool>::type
less(T a, T b) {
// ....
}
这篇关于模板专门化和enable_if问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!