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 

基本的に、 orを引数として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 では必要なく、多くのコンパイラではまだ実装されていません。result_ofが無効な場合にエラーが発生しないように、独自の SFINAE チェックを実装するか、エラー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)...)有効でない場合、2 番目のオーバーロードはオーバーロードの解決に参加しません。どちらも有効でない場合、呼び出しは不正な形式になり、両方が有効な場合、呼び出しはあいまいになります。

于 2013-01-06T17:37:45.263 に答える