c++ - 如何使用 enable_if 进行模板类成员的离线定义
问题描述
我正在尝试了解的用法,enable_if
但我确实遇到了一些困难。在这里,我编写了一个似乎无法按预期工作的测试代码。
#include <iostream>
template <typename T>
class Base{
public:
template <typename U>
U Compute(U a, U b);
};
using AddOperation = Base<int>;
template<>
template<typename U>
typename std::enable_if<!std::is_same<U, bool>::value, U>::type
AddOperation::Compute(U a, U b){
return a + b;
}
int main(){
Base<int> b;
std::cout << b.Compute<int>(10, 2) << std::endl;
std::cout << b.Compute<bool>(true, false) << std::endl;
return 0;
}
意图:不想为bool
类型启用计算
但在上面的代码中,它正在工作。如何确保 bool 的 Compute 函数没有被编译器专门化?
编辑1
最终目标是为 T=T1 启用Compute
U=bool 并为 T=T2 禁用Compute
U=bool。这是另一个示例代码,我试图通过它来实现相同的目标
#include <iostream>
enum class OpType{
INT,
BITWISE,
};
template <OpType T>
class Base{
public:
template <typename U>
typename std::enable_if<!std::is_same<U, bool>::value, U>::type
Compute(U a, U b);
};
using AddOperation = Base<OpType::INT>;
template<>
template<typename U>
typename std::enable_if<!std::is_same<U, bool>::value, U>::type
AddOperation::Compute(U a, U b){
std::cout << a << "," << b << std::endl;
return a + b;
}
using AndOperation = Base<OpType::BITWISE>;
template<>
template<typename U>
typename std::enable_if<std::is_same<U, bool>::value, U>::type
AndOperation::Compute(U a, U b){
return a & b;
}
int main(){
AddOperation b;
AndOperation a;
std::cout << b.Compute<int>(10, 2) << std::endl;
std::cout << a.Compute<bool>(true, true) << std::endl;
return 0;
}
解决方案
您也应该enable_if
在声明中使用,就像定义一样。
template <typename T>
class Base{
public:
template <typename U>
typename std::enable_if<!std::is_same<U, bool>::value, U>::type Compute(U a, U b);
};
事实上,clang拒绝了您当前的代码,因为声明和定义不匹配。
错误:“Compute”的外线定义与“Base”中的任何声明都不匹配
编辑(对于您添加的问题)
你可以
template <OpType T>
class Base{
public:
template <typename U, OpType X = T>
typename std::enable_if<
(X == OpType::INT && !std::is_same<U, bool>::value)
||
(X == OpType::BITWISE && std::is_same<U, bool>::value), U
>::type
Compute(U a, U b);
};
using AddOperation = Base<OpType::INT>;
template<>
template<typename U, OpType X>
typename std::enable_if<
(X == OpType::INT && !std::is_same<U, bool>::value)
||
(X == OpType::BITWISE && std::is_same<U, bool>::value), U
>::type
AddOperation::Compute(U a, U b){
std::cout << a << "," << b << std::endl;
return a + b;
}
using AndOperation = Base<OpType::BITWISE>;
template<>
template<typename U, OpType X>
typename std::enable_if<
(X == OpType::INT && !std::is_same<U, bool>::value)
||
(X == OpType::BITWISE && std::is_same<U, bool>::value), U
>::type
AndOperation::Compute(U a, U b){
return a & b;
}
然后
std::cout << b.Compute<int>(10, 2) << std::endl; // fine
std::cout << a.Compute<bool>(true, true) << std::endl; // fine
std::cout << b.Compute<bool>(true, true) << std::endl; // error, no matching function
std::cout << a.Compute<int>(10, 2) << std::endl; // error, no matching function
另一种方法是类模板专门化OpType::INT
,将和的实现分开OpType::BITWISE
。