c++ - 为什么 C++ lambda 重载的行为不如预期?

标签 c++ lambda overloading standards c++20

#include <type_traits>

template<typename T, typename... Args_>
concept IsCallable = std::is_invocable_v<T, Args_...>;

struct A
{
    int n = 0;

    void f(IsCallable<int&> auto const fn)
    {
        fn(n);
    }

    void f(IsCallable<int const&> auto const fn) const
    {
        fn(n);
    }
};

struct Lambda
{
    void operator()(auto& n) const
    {
        n = 1;
    }
};

int main()
{
    auto a = A{};
    a.f(Lambda{});               // ok
    a.f([](auto& n) { n = 1; }); // error: assignment of read-only reference 'n'
}

参见 online demo

为什么 C++ lambda 重载的行为不如预期?

最佳答案

  1. 您的问题几乎与 Hard error when using std::invoke_result_t with a generic lambda 重复.与另一个问题一样,如果您更改 lambda 以使其具有明确的 -> void 返回类型,您的代码将按您期望的方式工作,从而避免返回类型推导。
  2. 您的问题与另一个问题的区别在于,在您的问题中,您使用的是 std::invocable_v 而不是 std::invoke_result_t。但是,这种情况下的代码仍然是错误的,因为即使您没有要求,返回类型推导仍然会被触发。
  3. 该标准要求 is_invocable 来确定 INVOKE 表达式是否“在被视为未计算的操作数时格式正确”。 libstdc++ 和 libc++ 都使用 decltype 为此目的创建一个未计算的操作数,因此,很明显,必须进行返回类型推导。但在我看来 there is no way to avoid triggering return type deduction ,因此没有可能允许您的代码编译的标准库实现(这不是 GCC/Clang 中的错误)。

关于c++ - 为什么 C++ lambda 重载的行为不如预期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68778339/

相关文章:

c++ - 模板化成员函数的语法

c++ - 带有 std::function 的模板不直接匹配 lambda

c++ - 通用线程池类无法正常工作

C++ 重载和覆盖 - 无法使用类型为 '' 的右值初始化类型为 '' 的参数

c++ - omp中的 "C6993: code analysis ignores OpenMP construct"是什么意思?

c++ - 如何在 C++ 中实现一个函数作为一些可选参数?

android - 如何检查 kotlin 中的 lambda 是否为空

java - java认证考试的重载方法

c++ - 重载参数列表中与原始函数仅相差 "const"的函数

c++ - 没有数据的类的对象是否占用内存?