yohhoyの日記

技術的メモをしていきたい日記

一回だけ呼び出し可能な関数オブジェクト

std::asyncstd::launch::deferredで一回だけ呼び出し可能な関数オブジェクト(のようなモノ)。

#include <future>
#include <functional>  // bad_function_call
#include <utility>

template <class R>
class once_function {
  std::future<R> ftr_;
public:
  template <class F, class... Args>
  explicit once_function(F&& f, Args&&... args)
  {
    ftr_ = std::async(std::launch::deferred,
      std::forward<F>(f), std::forward<Args>(args)...);
  }

  R operator()()
  {
    if (!ftr_.valid())
      throw std::bad_function_call();
    return ftr_.get();
  }
};
int f(std::unique_ptr<int> p)
{
  return *p;
}

int main()
{
  std::unique_ptr<int> up( new int(42) );
  once_function<int> of(f, std::move(up));
  int v0 = of();  // v0 == 42
  int v1 = of();  // throw bad_function_call
}