How to understand the `callable` in the right way?

619 views Asked by At

As per the document, which says:

A Callable type is a type for which the INVOKE operation (used by, e.g., std::function, std::bind, and std::thread::thread) is applicable. This operation may be performed explicitly using the library function std::invoke. (since C++17)

Requirements

The type T satisfies Callable if Given f, an object of type T ArgTypes, suitable list of argument types R,

expressions must be valid:

std::declval()...) the expression is well-formed in unevaluated contextExpression Requirements INVOKE(f,suitable return type The following

Question 1:

If I understand correctly, given void foo(int) {}, std::function(foo) is not callable, whereas std::function(foo, 1) is callable. Am I right?

Question 2: What confuses me is the statement below.

As per the document, which says[emphasis mine]:

The class template std::packaged_task wraps any Callable target (function, lambda expression, bind expression, or another function object) so that it can be invoked asynchronously. Its return value or exception thrown is stored in a shared state which can be accessed through std::future objects.

As you see that the class template std::packaged_task wraps any Callable target, and std::function{foo} is not callable, but std::packged_task<void(int)> task{f}; compiles.

1

There are 1 answers

0
273K On

If one wants to be a successful professional, they do not stop reading the article on the introduction. If they continue reading the article and the referenced articles, they find all answers there.

Your first question is answered directly on that page:

  • otherwise, INVOKE(f, t1, t2, ..., tN) is equivalent to f(t1, t2, ..., tN) (that is, f is a FunctionObject).

Opening the reference:

A FunctionObject type is the type of an object that can be used on the left of the function call operator.

Therefore, void foo(int) {} is callable. The both std::function(foo) and std::function(foo, 1) will not compile. I guess you mean std::function f(foo), or std::function f{foo}, or std::function<void(int)> f(foo), the both are obviously callable, and I guess you confused std::bind(foo, 1) with std::function(foo, 1), that is also callable.

You know now, why std::packged_task<void(int)> task{f}; is compiled - because f is callable as it is figured out above.