I'm trying to use auto as the return type for a returned lambda function. Here's a minimal example that demonstrates a problem I'm having with this:
#include <iostream>
#include <memory>
auto
get_func()
{
auto i = std::make_unique<int>(2);
if (*i == 1) {
return [i=std::move(i)]() {
return *i;
};
}
return [](){ return 2; };
}
int
main(int argc, char* argv[])
{
auto func = get_func();
std::cout << "val: " << func() << std::endl;
return 0;
}
On my mac, I get the following compile error:
$ g++ -g -Wall -Werror -std=c++17 test.cc -o test
test.cc:13:5: error: 'auto' in return type deduced as '(lambda at test.cc:13:12)' here but deduced as '(lambda at test.cc:9:16)' in earlier return statement
return [](){ return 2; };
^
1 error generated.
Right, they're both deduced as lambda
. And they both have the same void(void)
signature. Am I seeing problems because they specify different captures? If so, what are my options for getting the same function call for the caller to work (as seen in the cout
call in main
).
Am I seeing problems because they specify different captures?
You would have seen a problem even if they were exactly the same, token for token.
Each lambda expression creates a unique closure type, which is different from any closure type created by any other lambda. There is no reconciling this difference, so auto
deduction cannot succeed.
You'll need to type erase the actual functor if you intend to return two different lambdas (either with std::function
, or a custom type that supports move only semantics). That, or perhaps roll the entire logic into a single lambda:
auto
get_func()
{
auto i = std::make_unique<int>(2);
return [i=std::move(i)]() {
if (*i == 1) {
return *i;
}
return 2;
};
}