dimanche 24 janvier 2016

How can I 'lift' an arbitrary function into a functor?

Consider the (templated) function

template <typename T> std::operator-(const T& lhs, const T& rhs)

in the standard C++ library, in <functional> we have the following construct (ignoring constexpr and the default void in C++14, and a convenience inheritance of binary_function):

  template<typename T>
  struct minus {
      T operator()(const T& lhs, const T& rhs) const {
          return operator-(lhs, rhs) 
      };
  };

so, the 'functor' (in standard library parlance) std::minus is a sort of a "lifting" of the function operator-. And we similarly have std::plus, std::multiplies and so on.

Now, suppose I wanted to achieve this same effect for an arbitrary function. Here's how I would do it with a macro (for the case of a known number of parameters, say 2)

#define CONCAT(s1,s2) s1##s2
#define EXPAND_THEN_CONCAT(s1,s2) CONCAT(s1,s2)
#define DEFINE_FUNCTOR(f, ret_type, param1_type, param2_type) \
    struct EXPAND_THEN_CONCAT(f,_functor)  { \
        ret_type operator()(param1_type x, param2_type y) const { \
            return f(x, y)  \
        }; \
    };

... but of course I want to do it the C++11 way (or the C++14 way if that helps). How would I do that?

I had the idea of passing f in as a template parameter somehow; but how do I make operator() have the same signature as f (and with a const marker)? For a fixed signature, I supposed it wouldn't be so difficult, and the code should look like std::minus - but in general I can't really see how it would be done.

I had thought about trying something similar to what I would use in a 'lifted invocation' of functions:

template<typename F, typename... Parameters>
inline void invoke(const F& f, Parameters... parameters) {
    f(parameters...);
}

but, again, that won't cut it - this will get me the execution I like, but not the signature I like; and I need that signature...

Aucun commentaire:

Enregistrer un commentaire