c++c++20c++-conceptsinvocable

Why is std::invocable concept blocking this code from compiling


I do not understand why neither the lambda nor the function are recognized as an std::invocable compliant types in the following code:

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

I am using GCC trunk with -std=c++2a flag enabled.


Solution

  • If you look at the definition of invocable (or in the standard):

    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 */
      };
    

    What this means:

    void f( std::invocable auto callback)
    

    And it might be clearer if we write it long-form:

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

    Is that F is invocable with no arguments - that it's a nullary function (Args... is an empty pack here). Neither your function nor your lambda are nullary functions - they're both unary, so the constraint correctly rejects those.

    What you probably want is:

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

    which checks if callback is invocable with a single argument of type int.