ArEss
ArEss

Reputation: 31

How to send as a function parameters, a lambda function with template parameters (...) plus those template parameters?

I know the title may be confusing. I created an "Array" data structure class which has a function called "Iterate". It accepts a function pointer (lambda) and iterates all the nodes with that function. Code:

    void Iterate(void(*function)(T* value))
    {
        if (Empty()) return;
        for (Node* iter = start; iter != nullptr; iter = iter->post)
            function(iter->value);
    }
// Function Call

DataStructure<int> test;
test.Iterate([](int i){ i = 0; });

This function works fine, but sometimes I need some arguments from outside to pass in. It can be done like this:

    template<class U>
    void Iterate(void(*function)(T* value, U a), U u)
    {
        if (Empty()) return;
        for (Node* iter = start; iter != nullptr; iter = iter->post)
            function(iter->value, u);
    }

// Function call
DataStructure<int> test;
test.Iterate<float>([](int i, float e){ i = e; }, 10.f);

And it works fine too, but I did not figure out how to do it with "...T". So the function can accept several arguments without having to overload the same function with x templates.

What I tried it:

    template<class ...U>
    void Iterate(void(*function)(T*, U...), U... u)
    {
        if (Empty()) return;

        for (Node* iter = start; iter != nullptr; iter = iter->post)
            function(iter->value, u);
    }

But it simply not works. It returns an error:

C++ no instance of overloaded function matches the argument list argument types are: (lambda []void (DataStructureType* data, Arg1 audio, Arg2 dt)->void, Arg1, Arg2)object type is: DataStructure<DataStructureType *>

Upvotes: 0

Views: 79

Answers (1)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122350

Better not require a conversion to function pointer when not necessary. Only non capturing lambdas can convert to a function pointer. Once you fix that you can use a lambda expression that captures the additional parameter:

template <typename F>
void call_it(F f) {
     for (int i=0;i<100;++i) f(i);
}

int main() {
    auto f1 = [](int i,float x) {return i*x; };
    float z = 0.2f;
    call_it( [&](int i) { return f1(i,z); });
}

The problem with our approach is that you cannot have implicit conversions and template argument deduction at the same time. If you use an explicit cast it works:

template<class T,class ...U>
void iterate(void(*function)(T, U...), U... u) {
            function(42, u...);
}

void foo(int,float) {}

int main() {
    auto f1 = [](int i,float x) {};    
    iterate(static_cast<void(*)(int,float)>(f1),42.f);
}

Upvotes: 2

Related Questions