In c++ 11, how to invoke an arbitrary callable object?

北城以北 提交于 2019-11-26 23:29:11

问题


The concept of callable is defined in http://en.cppreference.com/w/cpp/concept/Callable.

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

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


回答1:


This is exactly what std::invoke does, but it won't be standard until C++17. You can make your own version, but it can be pretty complicated if it is fully general.

Here's 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;
}



回答2:


Rather than implementing INVOKE yourself, use one of the library features that uses it. In particular, std::reference_wrapper works. Thus you can have 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 didn't forward f because std::reference_wrapper requires that the object passed in is not an rvalue. Using std::bind instead of std::ref doesn't fix the problem. What this means is that for a function object like this:

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

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

I found the technique from this paper




回答3:


Use boost::hof::apply:

#include <boost/hof/apply.hpp>

// ...
boost::hof::apply(f, args...);

boost::hof::apply performs the same operation that INVOKE does.


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



来源:https://stackoverflow.com/questions/32918679/in-c-11-how-to-invoke-an-arbitrary-callable-object

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!