Considering this well-known C++ pattern :
template <class... Ts> struct overload : Ts... { using Ts::operator()...; };
template <class... Ts> overload(Ts...) -> overload<Ts...>; // clang needs this deduction guide,
// even in C++20 for some reasons ...
I wonder why declaring one of the parameter as a mutable lambda changes the override resolution.
Live example here on godbolt :
#include <iostream>
template <class... Ts> struct overload : Ts... { using Ts::operator()...; };
template <class... Ts> overload(Ts...) -> overload<Ts...>; // clang needs this deduction guide,
// even in C++20 for some reasons ...
auto main() -> int
{
auto functor_1 = overload{
[](int &&){
std::cout << "int\n";
},
[](auto &&) { // making this lambda `mutable` makes deduction mismatch ?
std::cout << "smthg else\n";
}
};
functor_1(42); // prints `int`
auto functor_2 = overload{
[](int &&){
std::cout << "int\n";
},
[](auto &&) mutable {
std::cout << "smthg else\n";
}
};
functor_2(42); // prints `smth else`
}
With
auto functor = overload{
[](int &&){
std::cout << "int\n";
},
[](auto &&) {
std::cout << "smthg else\n";
}
};
functor(42); // prints `int`
both closures have const
qualified operator()
's so int&&
is a better match as it is not a template.
With
auto functor = overload{
[](int &&){
std::cout << "int\n";
},
[](auto &&) mutable {
std::cout << "smthg else\n";
}
};
functor(42); // prints `smthg else`
Your auto&&
closure is not const
qualified anymore, meaning there is no const
qualification adjustment that needs to happen in order to call it. This makes that overload an identity exact match, while the int&&
overload needs a const
qualification adjustment. The identity exact match beats out a const
qualification adjustment exact match per [tab:over.ics.scs] so that is why you see the auto&&
version called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With