是否可以根据模板参数的值有条件地编译函数中的语句?例如:
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>
and foo<int,1>
是不同的类,因此不可能定义一个不关心 chk 是 0 还是 1 的函数(比如watch(foo<int>)
).
我特别关注的应用程序是一个观察者,对于某些类型,我只希望观察者在值实际发生变化时得到通知,而对于其他类型,我希望观察者始终得到通知(对于那些我不希望发生的类型)必须定义一个 != 运算符)。
如果没有两个单独的类,这可能吗?
如果没有两个单独的类,这可能吗?
是的。如果您不想专门化您的类,以避免代码重复,您可以使用 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);
}
这个想法是right的定义doSomething
在编译时选取,它取决于模板参数的值chk
。另一个定义按照预期被简单地丢弃,并且根本不可用。
请注意,为了使 sfinae 表达式发挥作用,trigger
模板参数必须是成员函数模板的实际参数。这就是为什么你必须这样定义它:
template<bool trigger = chk>
sfinae_expression_based_on_enable_if
doSomething(T new_val) { /* ... */ }
在运行时看到它coliru http://coliru.stacked-crooked.com/a/76921c3a35c341bc.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)