I have a struct with a method called call which has a const overload. The one and only argument is a std::function which either takes a int reference or a const int reference, depending on the overload.
The genericCall method does exactly the same thing but uses a template parameter instead of a std::function as type.
struct SomeStruct {
int someMember = 666;
void call(std::function<void(int&)> f) & {
f(someMember);
std::cout << "call: non const\n";
}
void call(std::function<void(const int&)> f) const& {
f(someMember);
std::cout << "call: const\n";
}
template <typename Functor>
void genericCall(Functor f) & {
f(someMember);
std::cout << "genericCall: non const\n";
}
template <typename Functor>
void genericCall(Functor f) const& {
f(someMember);
std::cout << "genericCall: const\n";
}
};
When I now create this struct and call call with a lambda and auto & as argument the std::function always deduces a const int & despite the object not being const.
The genericCall on the other hand deduces the argument correctly as int & inside the lamdba.
SomeStruct some;
some.call([](auto& i) {
i++; // ?? why does auto deduce it as const int & ??
});
some.genericCall([](auto& i) {
i++; // auto deduces it correctly as int &
});
I have no the slightest clue why auto behaves in those two cases differently or why std::function seems to prefer to make the argument const here. This causes a compile error despite the correct method is called. When I change the argument from auto & to int & everything works fine again.
some.call([](int& i) {
i++;
});
When I do the same call with a const version of the struct everything is deduced as expected. Both call and genericCall deduce a const int & here.
const SomeStruct constSome;
constSome.call([](auto& i) {
// auto deduces correctly const int & and therefore it should
// not compile
i++;
});
constSome.genericCall([](auto& i) {
// auto deduces correctly const int & and therefore it should
// not compile
i++;
});
If someone could shine some light on this I would be very grateful!
For the more curious ones who want to dive even deeper, this problem arose in the pull request: https://github.com/eclipse-iceoryx/iceoryx/pull/1324 while implementing a functional interface for an expected implementation.