繁体   English   中英

如何为其他类成员函数编写模板包装器方法?

[英]How to write a template wrapper method for other class member functions?

我尝试使用不同的参数为不同的函数创建模板化包装器。 设置是A类,基本实现了两个方法foobar 另一个B类应包装这些方法并添加新功能。

以下链接的解决方案非常适用于非类函数: c ++ 11:模板化包装函数

但是如果我尝试从另一个类调用方法,我会收到错误。

#include <algorithm>
#include <functional>
#include <iostream>

class A
{
public:
    void foo(int x) {
        std::cout << "Foo: " << x << std::endl;
    }

    void bar(int x, float y) {
        std::cout << "Bar: " << x << ", " << y << std::endl;
    }
};

class B
{
public:
    void fooAndMore(int x) {
        foobarWrapper(&A::foo, 1);
    }

    void barAndMore(int x, float y) {
        foobarWrapper(&A::bar, 1, 3.5f);
    }

    template<typename  T, typename... Args>
    void foobarWrapper(T&& func, Args&&... args)
    {
        std::cout << "Start!" << std::endl;
        std::forward<T>(func)(std::forward<Args>(args)...);
        std::cout << "End!" << std::endl;
    }
};

int main()
{
    B b;
    b.fooAndMore(1);
    b.barAndMore(2, 3.5f);
}

我期待这样的事情:

Start!
Foo: 1
End!
Start!
Bar: 1, 3.5
End!

但相反,我得到:

error C2064: term does not evaluate to a function taking 1 arguments
note: see reference to function template instantiation 'void B::foobarWrapper<void(__thiscall A::* )(int),int>(T &&,int &&)' being compiled
    with
    [
        T=void (__thiscall A::* )(int)
    ]

error C2064: term does not evaluate to a function taking 2 arguments
note: see reference to function template instantiation 'void B::foobarWrapper<void(__thiscall A::* )(int,float),int,float>(T &&,int &&,float &&)' being compiled
    with
    [
        T=void (__thiscall A::* )(int,float)
    ]

不知道怎么解决这个问题?

最简单的解决方法是使A类的成员函数是static 见在线

class A
{
public:
    static void foo(int x) {
    ^^^^^^
        std::cout << "Foo: " << x << std::endl;
    }

    static void bar(int x, float y) {
    ^^^^^^
        std::cout << "Bar: " << x << ", " << y << std::endl;
    }
};

否则,您需要传递A类的实例以在foobarWrapper函数中调用其成员函数。 使用lambdas,您可以将它们打包到可调用的func并传递给foobarWrapper

见在线

class B
{
public:
    void fooAndMore(const A& a_obj, int x) {
        foobarWrapper([&]() { return a_obj.foo(x); });
        //            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Args captured to the lambda
    }

    void barAndMore(const A& a_obj, int x, float y) {
        foobarWrapper([&]() { return a_obj.bar(x, y); });
        //            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  Args captured to the lambda
    }

    template<typename  T>
    void foobarWrapper(T&& func)   // no Args needed any more (@credits Jarod42)
    {
        std::cout << "Start!" << std::endl;
        std::forward<T>(func)();   // simply call the func
        std::cout << "End!" << std::endl;
    }
};

int main()
{
    B b;
    b.fooAndMore(A{}, 1);       // pass a temporary A object
    b.barAndMore(A{}, 2, 3.5f);
}

试试这个,

#include <algorithm>
#include <functional>
#include <iostream>

class A
{
public:
    void foo(int x) {
        std::cout << "Foo: " << x << std::endl;
    }

    void bar(int x, float y) {
        std::cout << "Bar: " << x << ", " << y << std::endl;
    }
};

class B
{
public:
    void fooAndMore(int x) {
        foobarWrapper(&A::foo, x);
    }

    void barAndMore(int x, float y) {
        foobarWrapper(&A::bar, x, y);
    }

    template<typename  T, typename... Args>
    void foobarWrapper(T func, Args&&... args)
    {
        std::cout << "Start!" << std::endl;

        auto caller = std::mem_fn( func); // Newly added lines
        caller( A(), args...);  // Newly added line

        std::cout << "End!" << std::endl;
    }
};

int main()
{
    B b;
    b.fooAndMore(1);
    b.barAndMore(2, 3.5f);
}

输出:

Start!
Foo: 1
End!
Start!
Bar: 2, 3.5
End!

有关详细信息,请参阅此链接std :: mem_fn

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM