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.