C++ 重载模式:使用可变 lambda 调用解析

Gus*_*uss 15 c++ c++17

考虑到这个众所周知的 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 ...
Run Code Online (Sandbox Code Playgroud)

我想知道为什么将参数声明为可变 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`
}
Run Code Online (Sandbox Code Playgroud)

Nat*_*ica 9

auto functor = overload{
    [](int &&){
        std::cout << "int\n";
    },
    [](auto &&) {
        std::cout << "smthg else\n";
    }
};
functor(42); // prints `int`
Run Code Online (Sandbox Code Playgroud)

两个闭包都有const限定的operator()'s 所以int&&是更好的匹配,因为它不是模板。

auto functor = overload{
    [](int &&){
        std::cout << "int\n";
    },
    [](auto &&) mutable {
        std::cout << "smthg else\n";
    }
};
functor(42); // prints `smthg else`
Run Code Online (Sandbox Code Playgroud)

您的auto&&关闭const不再是合格的,这意味着不需要进行任何const资格调整来调用它。这使得重载成为身份完全匹配,而int&&重载需要const资格调整。身份完全匹配优于const每个[tab:over.ics.scs]的资格调整完全匹配,这就是您看到auto&&调用版本的原因。