簡體   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