c++boostboost-function

Storing boost::function object with variable number of arguments


What I'm trying to achieve is creating a struct which stores any kind of method. I can later call struct_object.run() to run the method I've stored.

This method can return any kind of value and, most importantly, use any amount of parameters; however, I can't get around the "any amount of parameters" issue.

Mind you, the following code doesn't even build, mostly because I have no clue on what the correct syntax would be like.

ApplicationPair.h

template<typename T, typename... Args>
struct ApplicationPair
{
    ApplicationPair(boost::function<T()> func, Args... arguments )
    {
        _func = func(Args::arguments...);
    }

    ApplicationPair() = delete;

    void run(); 
    boost::function<T(Args...)> _func;
};

#endif

And then, what I'd like to do is the following:

main.cpp

template<typename T, typename... Args>
void ApplicationPair<T,Args...>::run()
{
    this->_func;
}

//TEST

int counter = 0;

void HelloWorld()
{
    std::cout << "HelloWorld\n";
}

void printNumber(int i)
{
    std::cout << "Print: " << i << std::endl;
}

void increaseCounter(int x)
{
   counter+=x;
}

int main()
{
    ApplicationPair<void> p1(HelloWorld);
    ApplicationPair<void> p2(printNumber, 5);
    ApplicationPair<void> p3(increaseCounter, 10);
    p1.run();
    p2.run();
    p3.run();
    return 0;
}

Basically, the methods I want to store shouldn't be modified or adapted in any way: I want to be able to create any kind of method without caring about the fact that struct ApplicationPair will store it for its own personal use.

All I get with this though is a long string of errors like:

error: in declaration ‘typename boost::enable_if_c<(! boost::is_integral::value), boost::function&>::type boost::function::operator=(Functor)’


Solution

  • In the below line:

    ApplicationPair<void> p2(printNumber, 5);
    

    you have to specify all types in template arguments list, not only void as return type, int as argument of constructor should also be added. Now args... is empty. What is wrong. The same with p3.

    Make constructor as templated method taking paramters pack as argument for your callable:

    template<class F, class ... Args>
    ApplicationPair(F&& func, Args... arguments )
    {
        _func = boost::bind(std::forward<F>(func),arguments...);
    }
    

    then args... can be deduced when invoking constructor. Your class template takes only a type for return value.

    template<class Ret>
    struct ApplicationPair {
        template<class F, class ... Args>
        ApplicationPair(F&& func, Args... arguments )
        {
            _func = boost::bind(std::forward<F>(func),arguments...);
        }
        ApplicationPair() = delete;
        void run() {
            this->_func();
        }
        boost::function<Ret()> _func;
    };
    

    In constructor boost::bind is used to bind passed parameters to callable. You don't store parameters anywhere, therefore they must be bound in functor created by boost::bind.

    Uses:

    ApplicationPair<void> p1(HelloWorld);
    ApplicationPair<void> p2(printNumber, 5);
    ApplicationPair<void> p3(increaseCounter, 10);
    

    Demo


    Don't use boost::bind, it is limited to handle only max 9 arguments.