是否可以根据模板参数的值有条件地编译函数中的语句?例如:
template<typename T, bool chk>
class subject
{
public:
// the ideal case
void doSomething(T new_val)
{
if(chk)
{
if(new_val != val)
//do_something only if new_val is different from val
}
else
{
//do_something even if new_val and val are equal
}
}
//or if that's not possible, if chk = 0 use this method
void doSomething(T new_val)
{
//do_something even if new_val and val are equal
}
// and if chk = 1 use this method
void doSomething(T new_val)
{
if(new_val != val)
//do_something only if new_val is different from val
}
T val;
};
捕获是基于 chk 的值我什至不想要语句 if(new_val!=val)
编译到函数中(因为那时使用的每个类型 T 都必须定义一个 != 运算符)。
我想这种方法的一个缺点是 foo<int,0>
和 foo<int,1>
是不同的类,因此不可能定义一个不关心 chk 是 0 还是 1 的函数(比如 watch(foo<int>)
)。
我特别关注的应用程序是一个观察者,对于某些类型,我只希望观察者在值实际发生变化时得到通知,而对于其他类型,我希望观察者始终得到通知(对于那些我不希望的类型' 想要定义一个 != 运算符)。
如果没有两个单独的类,这可能吗?
最佳答案
Is this possible without having two separate classes?
是的,是的。如果您不想专门化您的类,以避免代码重复,您可以使用如下例中的 sfinae 表达式:
#include <type_traits>
#include <iostream>
template<typename T, bool chk>
struct subject {
template<bool trigger = chk>
std::enable_if_t<trigger>
doSomething(T new_val) {
if(new_val != val) {
std::cout << "new_val != val" << std::endl;
} else {
std::cout << "new_val == val" << std::endl;
}
}
template<bool trigger = chk>
std::enable_if_t<not trigger>
doSomething(T new_val) {
std::cout << "who cares?" << std::endl;
}
T val;
};
int main() {
subject<int, true> s1{0};
s1.doSomething(0);
s1.doSomething(1);
subject<int, false> s2{0};
s2.doSomething(0);
s2.doSomething(1);
}
这个想法是 doSomething
的正确定义是在编译时选择的,它取决于模板参数 chk
的值.另一个定义只是按预期被丢弃,根本不可用。
请注意,要使 sfinae 表达式起作用,trigger
模板参数必须是成员函数模板的实际参数。这就是为什么你必须这样定义它:
template<bool trigger = chk>
sfinae_expression_based_on_enable_if
doSomething(T new_val) { /* ... */ }
在 coliru 上运行时查看它.
关于C++根据模板参数值更改成员函数定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42603686/