Search code examples
c++templatesvariadic-templates

Call a function using expansion pack on a same function


I would like to be able to call a function over any number of arguments, with each argument's value supplied by another function:

template <typename T, std::size_t N>
class MyClass
{
public:
    void doSomething()
    {
        doSomethingProxy(std::make_index_sequence<N>());
    }

private:
    template <std::size_t... I>
    void doSomethingProxy(std::index_sequence<I...>)
    {
        m_obj.doSomething({get()...}); // T::doSomething() expects an object whose constructor has N number of arguments, and I would like to call the get() function for each argument of said constructor, N times
    }
    
    int get() { return 0; }

    T m_obj{};
};

However doing the above results in the error

error: expansion pattern get() contains no parameter packs

I think the issue is that get()... does not depend on I, but I'm not sure how to solve this problem.


Solution

  • (I,get()) is using the parameter pack and results in get() (comma operator, evaluates both operands, returns the rhs). To silence a warning about no effect of lhs of comma operator you might need to write ((void)I,get()):

    #include <cstdint>
    #include <utility>
    
    template <typename T, std::size_t N>
    class MyClass
    {
    public:
        void doSomething()
        {
            doSomethingProxy(std::make_index_sequence<N>());
        }
    
    private:
        template <std::size_t... I>
        void doSomethingProxy(std::index_sequence<I...>)
        {
            m_obj.doSomething({ ((void)I,get())... }); 
        }
        
        int get() { return 0; }
    
        T m_obj{};
    };