In C ++ 11, how to call an arbitrary called object?

The concept of the called is defined at http://en.cppreference.com/w/cpp/concept/Callable .

Suppose I have a callable object f that has one argument of type T * and returns a type of void . f can be any type being invoked (function object, pointer to a member function, pointer to a data element, etc.). How can i call f ?

Just calling f (x) fails, since f can be a pointer to a member function or data element. Is there an easy way to call f ? One possible solution is std :: bind (f, x) (), but this solution becomes more complex if f has more arguments.

+9
source share
3 answers

This is exactly what std::invoke does, but it will not be standard until C ++ 17. You can make your own version, but it can be quite complicated if it is completely general.

Here is the basic idea for two cases (code taken from cppreference.com):

 template <class F, class... Args> inline auto INVOKE(F&& f, Args&&... args) -> decltype(std::forward<F>(f)(std::forward<Args>(args)...)) { return std::forward<F>(f)(std::forward<Args>(args)...); } template <class Base, class T, class Derived> inline auto INVOKE(T Base::*pmd, Derived&& ref) -> decltype(std::forward<Derived>(ref).*pmd) { return std::forward<Derived>(ref).*pmd; } 
+7
source

Instead of implementing INVOKE yourself, use one of the functions of the library that uses it . In particular, std::reference_wrapper works. So you can get the effect of std::invoke(f, args...) with std::ref(f)(args...) :

 template<typename F, typename... Args> auto invoke(F f, Args&&... args) -> decltype(std::ref(f)(std::forward<Args>(args)...)) { return std::ref(f)(std::forward<Args>(args)...); } 

I did not forward f because std::reference_wrapper requires that the passed object is not a value. Using std::bind instead of std::ref does not solve the problem. This means that for such a functional object:

 struct F { void operator()() && { std::cout << "Rvalue\n"; } void operator()() const& { std::cout << "Lvalue\n"; } }; 

invoke(F{}) will print an Lvalue , while std::invoke(F{}) in C ++ 17 will print an Rvalue .

I found the technique from this article.

+6
source

Use boost::hof::apply :

 #include <boost/hof/apply.hpp> // ... boost::hof::apply(f, args...); 

boost::hof::apply performs the same operation as INVOKE .


Alternatively, use boost::hana::apply , which does the same

0
source

All Articles