处理方法结果的可变参数模板
Variadic template for processing method result
假设我有一个 class 和一些方法:
class Foo {
bool someMethodA(int someParamA, double someParamB, int someParamC);
bool someMethodB(double someParamA);
bool someMethodC(double someParamA);
...
}
每种方法都有不同的签名。有没有方便的方法来调用这些方法,以便在 true(成功)时调用通知方法?
notifySuccess();
执行此操作的宏是:
// Call a function notifyAll() on success
#define NOTIFY_ON_SUCCESS(func) \
bool success = func; \
if (success) { \
notifySuccess(); \
} \
return success;
有人建议有一种方法可以使用可变模板代替吗?类似于:
template <typename... ARGS>
bool CallImplAndNotify(bool (&SceneImpl::*func)(ARGS...), ARGS... args) {
bool result = func(args...);
...
}
template <class... Args, class...Ts>
bool CallImplAndNotify(bool (&SceneImpl::*func)(Args...), Ts&&... ts) {
bool result = (this->*func)(std::forward<Ts>(ts)...);
if(result) notify_on_success();
return result;
}
或者:
template<class T>struct tag_t{using type=T;};
template<class T>using block_deduction=typename tag_t<T>::type;
template <class... Args>
bool CallImplAndNotify(bool (&SceneImpl::*func)(Args...), block_deduction<Args>... args) {
bool result = (this->*func)(std::forward<Args>(args)...);
if(result) notify_on_success();
return result;
}
第一个可能稍微更有效,第二个允许 {}
样式构造并传递 NULL
标记而不是 nullptr
。
模板需要稍微充实,但你走对了:
#include <type_traits>
#include <functional>
#include <iostream>
void notifySuccess()
{
std::cout << "Success" << std::endl;
}
template <typename Obj, typename... ARGS,
typename ...Params>
bool CallImplAndNotify(Obj &obj, bool (Obj::*func)(ARGS...),
Params && ...params)
{
if ((obj.*func)(std::forward<Params>(params)...))
{
notifySuccess();
return true;
}
return false;
}
class Foo {
public:
bool someMethodA(int someParamA, double someParamB, int someParamC)
{
return true;
}
bool someMethodB(double someParamA)
{
return false;
}
bool someMethodC(double someParamA)
{
return true;
}
};
int main()
{
Foo f;
CallImplAndNotify(f, &Foo::someMethodA, 0, 1.0, 2.0);
CallImplAndNotify(f, &Foo::someMethodB, 1.0);
CallImplAndNotify(f, &Foo::someMethodC, 1.0);
return 0;
}
似乎一个简单的函数就可以解决问题:
bool NotifyOnSuccess(bool b) {
if (b) {
notifySuccess();
}
return b;
}
并称它为:
NotifyOnSuccess(foo.someMethodA(42, 5.1, 69));
NotifyOnSuccess(foo.someMethodB(5.1));
假设我有一个 class 和一些方法:
class Foo {
bool someMethodA(int someParamA, double someParamB, int someParamC);
bool someMethodB(double someParamA);
bool someMethodC(double someParamA);
...
}
每种方法都有不同的签名。有没有方便的方法来调用这些方法,以便在 true(成功)时调用通知方法?
notifySuccess();
执行此操作的宏是:
// Call a function notifyAll() on success
#define NOTIFY_ON_SUCCESS(func) \
bool success = func; \
if (success) { \
notifySuccess(); \
} \
return success;
有人建议有一种方法可以使用可变模板代替吗?类似于:
template <typename... ARGS>
bool CallImplAndNotify(bool (&SceneImpl::*func)(ARGS...), ARGS... args) {
bool result = func(args...);
...
}
template <class... Args, class...Ts>
bool CallImplAndNotify(bool (&SceneImpl::*func)(Args...), Ts&&... ts) {
bool result = (this->*func)(std::forward<Ts>(ts)...);
if(result) notify_on_success();
return result;
}
或者:
template<class T>struct tag_t{using type=T;};
template<class T>using block_deduction=typename tag_t<T>::type;
template <class... Args>
bool CallImplAndNotify(bool (&SceneImpl::*func)(Args...), block_deduction<Args>... args) {
bool result = (this->*func)(std::forward<Args>(args)...);
if(result) notify_on_success();
return result;
}
第一个可能稍微更有效,第二个允许 {}
样式构造并传递 NULL
标记而不是 nullptr
。
模板需要稍微充实,但你走对了:
#include <type_traits>
#include <functional>
#include <iostream>
void notifySuccess()
{
std::cout << "Success" << std::endl;
}
template <typename Obj, typename... ARGS,
typename ...Params>
bool CallImplAndNotify(Obj &obj, bool (Obj::*func)(ARGS...),
Params && ...params)
{
if ((obj.*func)(std::forward<Params>(params)...))
{
notifySuccess();
return true;
}
return false;
}
class Foo {
public:
bool someMethodA(int someParamA, double someParamB, int someParamC)
{
return true;
}
bool someMethodB(double someParamA)
{
return false;
}
bool someMethodC(double someParamA)
{
return true;
}
};
int main()
{
Foo f;
CallImplAndNotify(f, &Foo::someMethodA, 0, 1.0, 2.0);
CallImplAndNotify(f, &Foo::someMethodB, 1.0);
CallImplAndNotify(f, &Foo::someMethodC, 1.0);
return 0;
}
似乎一个简单的函数就可以解决问题:
bool NotifyOnSuccess(bool b) {
if (b) {
notifySuccess();
}
return b;
}
并称它为:
NotifyOnSuccess(foo.someMethodA(42, 5.1, 69));
NotifyOnSuccess(foo.someMethodB(5.1));