查看这样一个简单的模板场景:
class A {
public:
int work();
};
class B {
public:
int work();
};
class ObjectManager {
public:
static void manage( A& obj );
// manage not defined for class B
};
template<class T>
doStuff( T t ) {
t.work();
....
ObjectManager::manage(t);
};
A a;
B b;
doStuf(a);
doStuff(b);
我想知道,对ObjectManager::manage
实施条件调用的最简洁方法是什么?模板函数应该在编译时确定是否为给定的ObjectManager::manage(T t)
定义了T
,并且仅在它被激活时激活某些代码行。我猜有一些嵌套模板调用的解决方案,但对我来说最好只是将函数保持为一个整体。
答案 0 :(得分:5)
请注意,目前您的班级成员都是私人的。它们应该公开。
template<class T>
auto call_manage(T* t) -> decltype(ObjectManager::manage(*t)){
return ObjectManager::manage(*t);
}
void call_manage(...) {}
template<class T>
void doStuff( T t ) {
t.work();
//....
call_manage(std::addressof(t)); // smack whoever overloaded unary
// operator & in the head first
}
如果表达式ObjectManager::manage(*t)
格式正确,则函数模板的替换成功,它总是比...
更好的匹配,因此它被调用。否则,do-nothing过载是唯一可行的功能。
对于喜欢参考的人:
template<class T>
auto call_manage(T& t) -> decltype(ObjectManager::manage(t)){
return ObjectManager::manage(t);
}
template<class... T>
void call_manage(T&&...) {}
template<class T>
void doStuff( T t ) {
t.work();
//....
call_manage(t);
}
在这种情况下,单参数重载比功能模板的部分排序规则的可变参数版本更专业,并且如果两者同样可行,则通过重载决策选择。您也可以点T&& t
并致电manage(std::forward<T>(t))
,以便完美转发。