处理方法结果的可变参数模板

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));