sunkue
sunkue

Reputation: 288

How can I make template codes using member-Function

class A
{
public:
    A* m_child;
    A* m_brother;
    int x;
    A(int num) :x{ num } {};
public:
    template<typename Pred, typename...Args>
    void ForFamily(Pred, Args&&... args) {
        if (m_child) Pred(m_child*, std::forward<Args>(args)...);
        if (m_brother) m_brother->Pred(std::forward<Args>(args)...);
    }
    void f(int a, int b) {
        cout << x + a + b;
    }
    void g(int a) {
        cout << a + x;
    }
};

I wanna make a Template_Func that works for evey m_child and m_brother. How I can make this works? I gonna use it like this way

int main()
{
    A a(1), b(2), c(3);
    a.m_child = &b;
    a.m_brother = &c;

    a.ForFamily(A::f, 1, 2);
    a.ForFamily(A::g, 1);
}

Upvotes: 0

Views: 77

Answers (1)

fabian
fabian

Reputation: 82451

Use a member function pointer as the first parameter of the member function. Note that I also added default initializations to the pointers to avoid undefined behavior, if those members are not initialized:

class A
{
public:
    A* m_child {nullptr};
    A* m_brother {nullptr};
    int x;
    A(int num) :x{ num } {};
public:
    template<typename... Args>
    void ForFamily(void (A::*funct)(Args...), Args&&... args)
    {
        if (m_child != nullptr)
        {
            (m_child->*funct)(std::forward<Args>(args)...);
        }
        if (m_brother != nullptr)
        {
            (m_brother->*funct)(std::forward<Args>(args)...);
        }
    }


    void f(int a, int b) {
        cout << x + a + b;
    }
    void g(int a) {
        cout << a + x;
    }
};

int main()
{
    A a(1), b(2), c(3);
    a.m_child = &b;
    a.m_brother = &c;

    a.ForFamily(&A::f, 1, 2);
    a.ForFamily(&A::g, 1);
}

You may want to place the functionality outside of class A though, e.g.

    template<typename Funct, typename... Args>
    void ForFamily(Funct funct, Args&&... args)
    {
        if (m_child != nullptr)
        {
            funct(m_child->x, std::forward<Args>(args)...);
        }
        if (m_brother != nullptr)
        {
            funct(m_brother->x, std::forward<Args>(args)...);
        }
    }
...

    a.ForFamily([](int x, int a, int b) { std::cout << (x + a + b);}, 1, 2);
    a.ForFamily([](int x, int a) { std::cout << (x + a);}, 1);

or

    template<typename Funct, typename... Args>
    void ForFamily(Funct funct, Args&&... args)
    {
        if (m_child != nullptr)
        {
            funct(*m_child, std::forward<Args>(args)...);
        }
        if (m_brother != nullptr)
        {
            funct(*m_brother, std::forward<Args>(args)...);
        }
    }
...

    a.ForFamily([](A& obj, int a, int b) { obj.f(a, b);}, 1, 2);
    a.ForFamily([](A& obj, int a) { obj.g(a);}, 1);

since those are more flexible. (Note that if I had a real application using lambdas usually I wouldn't bother passing them though ForFamily via forwarding but would simply bind/hardcode them to the lambda.)

Upvotes: 1

Related Questions