You can write a simple wrapper class that handles this part of it:
template <class T>
struct CallAndStore {
template <class F>
CallAndStore(F f) : t(f()) {}
T t;
T get() { return std::forward<T>(t); }
};
And specialize:
template <>
struct CallAndStore<void> {
template <class F>
CallAndStore(F f) { f(); }
void get() {}
};
You can improve usability with a small factory function:
template <typename F>
auto makeCallAndStore(F&& f) -> CallAndStore<decltype(std::declval<F>()())> {
return {std::forward<F>(f)};
}
Then use it.
template <typename F>
auto wrapAndRun(F fn) {
// foo();
auto&& result = makeCallAndStore(std::move(fn));
// bar();
return result.get();
}
Edit: with the std::forward
cast inside get
, this also seems to handle returning a reference from a function correctly.