tmlen tmlen - 2 months ago 6
C++ Question

Template argument for function type in C++

Here,

Wrapper::set
should be able to take any function or function object that matches the
int(int)
signature, and store it into the
std::function
. It should work with function pointers, lambdas, objects with
operator()
,
std::bind
expressions, etc.

#include <functional>

struct Wrapper {
using function_type = int(int);

std::function<function_type> func_;

template<typename Func> void set(Func func) { func_ = func; }
};


What would be the best form of
set
so that it works in all cases? I.e. one of


  • set(Func func) { func_ = func; }

  • set(Func&& func) { func_ = std::forward<Func>(func); }

  • set(Func& func) { func_ = func; }

  • set(const Func& func) { func_ = func; }


Answer

The simplest version:

void set(function_type f) {
    func_ = std::move(f);
}

The complex version:

template <class F,
    class = std::enable_if_t<std::is_assignable<std::function<function_type>&, F&&>::value>
    >
void set(F&& f) {
    func_ = std::forward<F>(f);
}

There's no reason to do anything else. Both of these handle every case gracefully and correctly, the simple case has an extra move, which for std::function isn't an expensive operation, so I would strongly prefer the simple version unless you have a compelling, proven performance requirement to need the complex one.

Comments