考虑到这个众所周知的C++模式:
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 ...
我想知道为什么将其中一个参数声明为可变lambda会改变重写解析。
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`
}
与
auto functor = overload{
[](int &&){
std::cout << "int\n";
},
[](auto &&) {
std::cout << "smthg else\n";
}
};
functor(42); // prints `int`
这两个闭包都有const限定的operator()
的,因此int&&
是更好的匹配项,因为它不是模板。
与
auto functor = overload{
[](int &&){
std::cout << "int\n";
},
[](auto &&) mutable {
std::cout << "smthg else\n";
}
};
functor(42); // prints `smthg else`
您的auto&&
闭包不再是常量限定的,这意味着调用它不需要进行常量限定调整。这使得该重载与标识完全匹配,而int&&
重载需要进行常量限定调整。identity的精确匹配胜过[tab:over.ics.scs]的常量限定调整的精确匹配,因此您看到调用auto&
版本的原因就在于此。