Yes. You use std::function when you don't want every function/structure, that accepts a function as an argument, to be infected with templates, and instead be a plain function/structure. Thanks to that:
* there will be only one instance of it;
* you'll be able to export such a function in public interface of a dynamic library without exposing its source code in a header file;
* compilation will be faster, because the compiler won't have to instantiate N different versions of a template;
* you'll see fewer scary template errors.
Your life as a human being will be happier.
Of course there are better alternatives to std::function in the wild, but the general idea remains.
std::invokable will just make working with templates nicer. But not working with templates is nicer still.
EDIT: You can think of std::function as the LSP inside C++. There is a famous matrix where rows are for editors, and columns are for languages. In case of std::function rows are functions accepting functions as arguments, and columns are functions passed as function arguments. The matrix represents template instantiations, when you use templates. By using std::function you avoid the matrix and instead have just two vectors of length N and M, if the matrix was NxM (N functions accepting functions as arguments, M functions passed as arguments).
Comments
With C++20 and the std::invocable concept, is there still much reason to use std::function?
Yes. You use std::function when you don't want every function/structure, that accepts a function as an argument, to be infected with templates, and instead be a plain function/structure. Thanks to that:
* there will be only one instance of it;
* you'll be able to export such a function in public interface of a dynamic library without exposing its source code in a header file;
* compilation will be faster, because the compiler won't have to instantiate N different versions of a template;
* you'll see fewer scary template errors.
Your life as a human being will be happier.
Of course there are better alternatives to std::function in the wild, but the general idea remains.
std::invokable will just make working with templates nicer. But not working with templates is nicer still.
EDIT: You can think of std::function as the LSP inside C++. There is a famous matrix where rows are for editors, and columns are for languages. In case of std::function rows are functions accepting functions as arguments, and columns are functions passed as function arguments. The matrix represents template instantiations, when you use templates. By using std::function you avoid the matrix and instead have just two vectors of length N and M, if the matrix was NxM (N functions accepting functions as arguments, M functions passed as arguments).