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:
std::function_v<F>
is true
std::function_v<std::remove_pointer_t<F>>
is true
std::function_v<std::remove_reference_t<F>>
is true
std::function_v<std::remove_pointer_t<std::remove_reference_t<F>>>
is true
std::is_member_function_pointer_v<F>
is true
std::is_member_function_pointer_t<std::remove_reference_t<F>>
is true
std::is_member_object_pointer_v<F>
is true
std::is_member_object_pointer_v<std::remove_reference_t<F>>
is true
std::is_class_v<F>
is true
and such that F::operator()
existsstd::is_class_v<std::remove_reference_t<F>>
is true
and such that std::remove_reference_t<F>::operator()
existsstd::is_union_v<F>
is true
and such that F::operator()
existsstd::is_union_v<std::remove_reference_t<F>>
is true
and such that std::remove_reference_t<F>::operator()
existsstd::remove_reference_t<F>
is a closure typeIs 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:
std::is_class_v<F>
is true
and such that F::operator()
existsstd::is_union_v<F>
is true
and such that F::operator()
existsbelongs 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?
R(Args...)
, R(Args...) noexcept
, R(Args......)
and R(Args......) noexcept
.operator()
member (including inherited);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, i.e. #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", i.e., #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
.