4

我努力了几个小时,但没能成功。

我有一个模板类自旋锁:

template<typename T> class spinlock {
  // ...
  volatile T *shared_memory;
};

我正在尝试创建这样的东西:

  // inside spinlock class
  template<typename F, typename... Ars>
  std::result_of(F(Args...))
  exec(F fun, Args&&... args) {
    // locks the memory and then executes fun(args...)
  };

但我正在尝试使用多态函数,以便我可以做到这一点:

spinlock<int> spin;

int a = spin.exec([]() {
  return 10;
});

int b = spin.exec([](int x) {
  return x;
}, 10); // argument here, passed as x

// If the signature matches the given arguments to exec() plus
// the shared variable, call it
int c = spin.exec([](volatile int &shared) {
  return shared;
}); // no extra arguments, shared becomes the
    // variable inside the spinlock class, I need to make
    // a function call that matches this as well

// Same thing, matching the signature
int d = spin.exec([](volatile int &shared, int x) {
  return shared + x;
}, 10); // extra argument, passed as x... should match too

// Here, there would be an error
int d = spin.exec([](volatile int &shared, int x) {
  return shared + x;
}); // since no extra argument was given 

基本上,我正在尝试创建一个exec接受F(Args...)F(volatile T &, Args...)作为参数的函数。

但我无法自动检测类型。我怎么能做到这一点?

4

1 回答 1

3

首先,这个签名不会编译:

// inside spinlock class
template<typename F, typename... Ars>
std::result_of(F(Args...))
exec(F fun, Args&&... args) {
  // locks the memory and then executes fun(args...)
};

返回类型必须是

typename std::result_of<F(Args...)>::type

如果您的编译器实现了 N3436,那么当不是有效表达式时,此函数将不参与重载解析fun(args...),但这在 C++11 中不是必需的,并且许多编译器尚未实现。您将需要实施自己的 SFINAE 检查以防止在无效result_of时给出错误,或者在没有的情况下重写它fun(args...)result_of

template<typename F, typename... Args>
auto
exec(F fun, Args&&... args) -> decltype(fun(std::forward<Args>(args)...))
{
  // locks the memory and then executes fun(args...)
}

然后你可以为需要传入额外参数的函数重载它:

template<typename F, typename... Args>
auto
exec(F fun, Args&&... args) -> decltype(fun(*this->shared_memory, std::forward<Args>(args)...))
{
  // locks the memory and then executes fun(*shared_memory, args...)
}

fun(std::forward<Args>(args)...)无效时,第一个重载将不参与重载决议。当fun(*this->shared_memory, std::forward<Args>(args)...)无效时,第二个重载将不参与重载决议。如果两者都无效,则调用将是格式错误的,如果两者都有效,则调用将是模棱两可的。

于 2013-01-06T17:37:45.263 回答