简体   繁体   中英

What are the types that are considered callables in C++?

I am trying to understand the hierarchy of concepts and types of things that can be passed as the first parameter of std::invoke.

Let's consider a type F such that there exist at least one combination of Args such that std::is_invokable_v<F, Args...> is true .

Question [1]: What are all the types F can be?

Here is a tentative list:

  • a function such as std::function_v<F> is true
  • a function pointer such that std::function_v<std::remove_pointer_t<F>> is true
  • a function reference such that std::function_v<std::remove_reference_t<F>> is true
  • a reference to a function pointer such that std::function_v<std::remove_pointer_t<std::remove_reference_t<F>>> is true
  • a pointer to member function such that std::is_member_function_pointer_v<F> is true
  • a reference to a pointer to member function such that std::is_member_function_pointer_t<std::remove_reference_t<F>> is true
  • a pointer to member object such that std::is_member_object_pointer_v<F> is true
  • a reference to pointer to member object such that std::is_member_object_pointer_v<std::remove_reference_t<F>> is true
  • a class such that std::is_class_v<F> is true and such that F::operator() exists
  • a reference to a class such that std::is_class_v<std::remove_reference_t<F>> is true and such that std::remove_reference_t<F>::operator() exists
  • a union such that std::is_union_v<F> is true and such that F::operator() exists
  • a reference to a union such that std::is_union_v<std::remove_reference_t<F>> is true and such that std::remove_reference_t<F>::operator() exists
  • a closure type
  • a reference to a closure type such that std::remove_reference_t<F> is a closure type

Is this list correct? Is there any other viable option?

Question [2]: Are closure types only the types of lambda expressions or is there other way in C++ to create something which would be considered as a closure type?

Question [3]: The standard sometimes talks about function objects: what in the list of question 1) is considered as a function object?

Question [4]: Do the following:

  • a closure type
  • a class such that std::is_class_v<F> is true and such that F::operator() exists
  • a union such that std::is_union_v<F> is true and such that F::operator() exists

belongs to a particular concept in the standard (basically something that has an operator() )? If not, what would be a good name (for example if such a thing has a common name in computer science or in other programming languages) for a type trait that would detect if a type satisfies one of the bullet points listed?

  1. Function types of the form R(Args...) , R(Args...) noexcept , R(Args......) and R(Args......) noexcept .
  2. (Possibly cv-qualified) pointers to #1.
  3. (Possibly cv-qualified) class types that have at least one public operator() member (including inherited);
  4. (Possibly cv-qualified) class types that have at least one public non-explicit conversion function to a) reference to #1, b) #2, or c) reference to #2 (including inherited);
  5. (Possibly cv-qualified) pointers to member.
  6. References to the above.

For #3, #4, and references thereto, there's the extra qualification that the cv-qualification and value category encoded in the type must be compatible with at least one such function.

"Function object types" are object types that can be called using the usual function call syntax, ie #2-#4. Pointers to member do not qualify because you can't call them with () .

A "callable type" by definition is either "a function object types or a pointer to member", ie, #2-#5.

Function types and reference types are not object types and are therefore neither function object types nor callable types, but can become one with the application of std::decay .

I think you missed a number of variations along the line of

  • a class such that std::is_class_v<F> is true and such that F inherits an operator()

As for closures and lambda's, note that C++ has no magic lambda's. Lambda's are just objects of class type, created via a convenient syntax. std::bind will also produce a Callable object, and this too can be considered a closure. But "closure" is a label with no exact meaning in C++ and should not be on the list, as noted by Nicol Bolas in the comments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM