Search code examples
c++templatesmember-pointersparameter-pack

Passing pointers to member to function object from template parameter pack


Bellow is sample code which demonstrates what I am trying to do.

basically I want to pass more than one pointer to member to class method which takes std::function object and variable number or arguments which are passed to target function object.

these variable parameters can be anything: variables, pointers to members etc..

I have no problem when working with plain variables, but how do expand paramter pack where parameters are pointers to members but function object expects POD data types?

How to take value of pointer to member in parameter pack and pass it to function object?

#include <cstddef>
#include <functional>


class Test
{
public:
    inline Test(std::uint32_t max);

    template<typename ReturnType, typename... Args>
    using Algorithm = std::function<ReturnType(Args...)>;

    // pointer to member
    // not used but would like to make use of it in 'RunTargetAlgo'
    template<typename T>
    using ParamType = T Test::*;

    // exectutor
    template<typename ReturnType, typename... Args, typename... Params>
    inline double RunTargetAlgo(Algorithm<ReturnType, Args...> target, Params... params);

    std::uint32_t mLoop = 0;
    const std::size_t mLoopMax;
    double mPrecision = 0;
};

Test::Test(std::uint32_t max) :
    mLoopMax(max)
{
}

template<typename ReturnType, typename ...Args, typename ...Params>
double Test::RunTargetAlgo(Algorithm<ReturnType, Args...> target, Params ...params)
{
    while (++mLoop <= mLoopMax)
        mPrecision += target(params...);    // How if Params == Test::ParamType ??

    // ... in real code we measure bunch of other stuff here...

    return mPrecision;
}

template<typename RetrunType>
RetrunType TestAlgorithm(std::uint32_t x, std::uint32_t y)
{
    // ...
    return RetrunType();
}

int main()
{
    namespace pl = std::placeholders;

    Test::Algorithm<double, std::uint32_t, std::uint32_t> algo =
        std::bind(TestAlgorithm<double>, pl::_1, pl::_2);

    Test t(50);

    // this works just fine!
    t.RunTargetAlgo(algo, 3u, 4u);

    // but how to run this?
    // I need pass fresh data to target algorithm, value of
    // pointer to members may change anytime.
    // but main issue here is how to extract these pointer from
    // parameter pack into actual values, but inside Test::RunTargetAlgo?
    t.RunTargetAlgo(algo, &Test::mLoop, &Test::mLoopMax);

    return 0;
}

Solution

  • As discussed in the comments, assuming you will have all arguments require the same action, you can simply apply any dereferencing/member access operation in the parameter pack expansion. E.g. for member pointers that should access the this instance:

    target(this->*params...);
    

    or if you pass object pointers directly (which seems much more straight-forward to me):

    target(*params...);
    
    //...
    
    t.RunTargetAlgo(algo, &t.mLoop, &t.mLoopMax);