【问题标题】:call member function with expanded tuple parms std::invoke vs std::apply使用扩展元组参数调用成员函数 std::invoke vs std::apply
【发布时间】:2017-06-27 09:36:33
【问题描述】:

我发现 std::invoke 使用一组参数调用每个可调用对象,std::apply 将元组作为参数扩展为可调用对象。

是否有两者的组合可以调用任何使用元组作为参数的可调用对象?

#include <iostream>
#include <tuple>
#include <functional>

class A
{
    private:
        int n;

    public:
        A( int _n ): n(_n){}

        void operator()(int x, double y )
        {
            std::cout << n << " " << x << " " << y << std::endl;
        }

        void MemFun( int x, double y )
        {
            std::cout << n << " " << x << " " << y << std::endl;
        }
};

int main()
{
    A a(100);
    std::invoke( a, 10, 1.23 );

    auto parm2 = std::make_tuple( 1,2.34);
    std::apply ( a, parm2 );

    std::invoke ( &A::MemFun, a, 4, 5.67 );

    // ???
    std::??apply_invoke?? ( &A::MemFun, a, parm2 );
}

【问题讨论】:

    标签: c++ tuples c++17


    【解决方案1】:

    你的意思是这样的吗?

    std::apply(&A::MemFun, std::tuple_cat(std::make_tuple(a), parm2));
    

    是否有两者的组合可以调用任何使用元组作为参数的可调用对象?

    std::apply 可用于调用任何可调用对象,因此我不太了解这里的问题。就像std::invoke 的成员函数一样:第一个参数需要是你要调用函数的对象。 std::apply 也是如此,其中传递的元组的第一个元素需要是您希望调用它的对象。

    如果您不喜欢指定 std::tuple_cat 等,您可以随时创建包装器:

    template<typename F, typename T, typename U>
    decltype(auto) apply_invoke(F&& func, T&& first, U&& tuple) {
        return std::apply(std::forward<F>(func), std::tuple_cat(std::forward_as_tuple(std::forward<T>(first)), std::forward<U>(tuple)));
    }
    

    【讨论】:

    • 我会使用forward_as_tupletie 而不是make_tuple,因为你不需要复制a
    • @JonathanWakely 感谢您的提示!
    【解决方案2】:

    std::apply( std::bind(&amp;A::MemFun, &amp;a, std::placeholders::_1, std::placeholders::_2), parm2 );怎么样?

    已编辑以包含建议和占位符

    【讨论】:

    • 最好使用 lambda 而不是 std::bind
    • 使用bind 是可以的,但是这个解决方案会复制a,所以最好使用std::ref(a) 或简单地使用&amp;a
    猜你喜欢
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 2013-02-01
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多