为什么 std::invocable 概念会阻止编译此代码

nya*_*108 1 c++ c++-concepts c++20 invocable

我不明白为什么std::invocable在以下代码中lambda 和函数都没有被识别为兼容类型:

#include <concepts>
#include <iostream>

void f( std::invocable auto callback)
{
    callback(47);
}

void function_callback(int i)
{
    std::cout << i << std::endl;
}

auto lambda_callback = [](int i )
{
    std::cout << i << std::endl;
};

int main(int) 
{
    f(&function_callback);
    f(lambda_callback);
}
Run Code Online (Sandbox Code Playgroud)

我正在使用-std=c++2a启用了标志的GCC 主干。

Bar*_*rry 8

如果您查看invocable(或在标准中)的定义:

template< class F, class... Args >
concept invocable =
  requires(F&& f, Args&&... args) {
    std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
      /* not required to be equality preserving */
  };
Run Code Online (Sandbox Code Playgroud)

这是什么意思:

void f( std::invocable auto callback)
Run Code Online (Sandbox Code Playgroud)

如果我们把它写成长格式可能会更清楚:

template <typename F>
    requires std::invocable<F>
void f(F callback);
Run Code Online (Sandbox Code Playgroud)

是否F可以不带参数调用- 它是一个空函数(Args...这里是一个空包)。您的函数和 lambda 都不是空函数——它们都是一元函数,因此约束正确地拒绝了它们。

你可能想要的是:

void f( std::invocable<int> auto callback)
Run Code Online (Sandbox Code Playgroud)

它检查是否callback可以使用 type 的单个参数调用int

  • @nyarlathotep108 概念永远不会被推导。概念被指定。 (4认同)
  • @nyarlathotep108 你会用这些信息做什么?您有一个模板,该模板以某种方式受限于可调用的类型 - 但您不知道如何实现?从一般意义上来说,甚至无法回答。 (2认同)
  • @nyarlathotep108:记住:约束应该表达你打算如何使用一个东西。你不会用“任何”参数来调用它;你将用*一些*参数来调用它。因此,您的约束应该表达您对该函数的使用的意图。 (2认同)