Handling void assignment in C++ generic programming

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.

Leave a Comment