Почему концепция std::invocable блокирует компиляцию этого кода

Я не понимаю, почему ни лямбда, ни функция не распознаются как std::invocable совместимые типы в следующем коде:

#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);
}

Я использую ствол GCC с -std=c++2a флаг включен.

1 ответ

Решение

Если вы посмотрите на определение 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 */
  };

Что это значит:

void f( std::invocable auto callback)

И будет понятнее, если мы напишем его в полной форме:

template <typename F>
    requires std::invocable<F>
void f(F callback);

В том, что Fвызывается без аргументов - это нулевая функция (Args...здесь пустая упаковка). Ни ваша функция, ни ваша лямбда не являются нулевыми функциями - они обе унарны, поэтому ограничение правильно их отклоняет.

Вероятно, вы хотите:

void f( std::invocable<int> auto callback)

который проверяет, если callback вызывается с одним аргументом типа int.

Другие вопросы по тегам