When you pass an overloaded function like f to std::apply, the compiler can’t peek inside the tuple to figure out which overload matches—it only sees an ambiguous callable and a single tuple argument. Because overload resolution happens before the tuple is unpacked, you need an extra layer (like a lambda) to forward the unpacked arguments and give the compiler enough information to pick the correct overload.
Why can’t std::apply figure out which overload I intend to use? Only one of them will work!
by Raymond Chen
From the article:
Consider the following:
void f(int, int); void f(char*, char*); void test(std::tuple<int, int> t) { std::apply(f, t); // error }The compiler complains that it cannot deduce the type of the first parameter.
I’m using
std::applyhere, but the same arguments apply to functions likestd::invokeandstd::bind.From inspection, we can see that the only overload that makes sense is
f(int, int)since that is the only one that accepts two integer parameters.But the compiler doesn’t know that
std::applyis going to try to invoke its first parameter with arguments provided by the second parameter. The compiler has to choose an overload based on the information it is given in the function call.

Add a Comment
Comments are closed.