Wulf0x67E7
Wulf0x67E7

Reputation: 53

using non-capturing lambda as function pointer argument to a variadic template function gives "no matching function call"

I am currently experimenting with writing a "foreach with" for an ecs.

template <typename... T>
void foreach (void (*func)(Entity e, T... args)){
  std::vector<Entity> intersection;
  // ... Find all entities with all the types
  for (size_t i = 0; i < intersection.size(); i++)
    func(intersection[i], *getComp<T>(intersection[i])...);
}

It's working perfectly with a function argument

void foo(Entity e, int i)
{
  setComp<int>(e, (int) e);
}

foreach(foo); // Works as expected

But not with the same function copy and pasted as lambda

foreach( // even if foreach<int>
    [](Entity e, int i) {
        setComp<int>(e, (int) e);
    }); // error "no matching function call" "no instance of template matches"

Changing foreach to accept lambdas

template <typename... T, typename F>
void foreach (F func){
  std::vector<Entity> intersection;
  // ... Find all entities with all the types
  for (size_t i = 0; i < intersection.size(); i++)
    func(intersection[i], *getComp<T>(intersection[i])...);
}

now produces an error "no match for call to" with lambda and "too few arguments to function" with foo, both at func(...);.

I'm probably overseeing something, but even after scouring google and SO I just can't find what.

I'll probably just gonna use the function pointer variant and give up on passing lambdas as that works at least, but would be very gratefull if somebody could point out what dumb me has overlooked.

Upvotes: 4

Views: 117

Answers (1)

max66
max66

Reputation: 66200

The problem is that with

template <typename... T>
void foreach (void (*func)(Entity e, T... args))

the variadic list of types T... is deduced from func arguments.

With

template <typename... T, typename F>
void foreach (F func)

the T... list can't be deduced anymore from func.

So you can't call

foreach( // even if foreach<int>
    [](Entity e, int i) {
        setComp<int>(e, (int) e);
    }); 

You have to explicit T...

// ....VVVVV
foreach<int>(
    [](Entity e, int i) {
        setComp<int>(e, (int) e);
    }); 

Upvotes: 2

Related Questions