C++ 中哪些类型被认为是可调用的?
What are the types that are considered callables in C++?
我试图理解可以作为 std::invoke 的第一个参数传递的概念和事物类型的层次结构。
让我们考虑一种类型 F
,其中存在至少一个 Args
的组合,使得 std::is_invokable_v<F, Args...>
是 true
。
问题[1]:F
可以有哪些类型?
这是一份暂定名单:
std::function_v<F>
等函数是true
- 一个函数指针使得
std::function_v<std::remove_pointer_t<F>>
是 true
- 一个函数引用使得
std::function_v<std::remove_reference_t<F>>
是 true
- 对函数指针的引用使得
std::function_v<std::remove_pointer_t<std::remove_reference_t<F>>>
是 true
- 指向成员函数的指针,使得
std::is_member_function_pointer_v<F>
是 true
- 对指向成员函数的指针的引用使得
std::is_member_function_pointer_t<std::remove_reference_t<F>>
是 true
- 指向成员对象的指针,使得
std::is_member_object_pointer_v<F>
是 true
- 对指向成员对象的指针的引用使得
std::is_member_object_pointer_v<std::remove_reference_t<F>>
是 true
- a class 使得
std::is_class_v<F>
是 true
并且 F::operator()
存在
- 对 class 的引用使得
std::is_class_v<std::remove_reference_t<F>>
是 true
并且 std::remove_reference_t<F>::operator()
存在
- 一个联合使得
std::is_union_v<F>
是 true
并且 F::operator()
存在
- 对联合的引用使得
std::is_union_v<std::remove_reference_t<F>>
是 true
并且 std::remove_reference_t<F>::operator()
存在
- 闭包类型
- 对闭包类型的引用使得
std::remove_reference_t<F>
是闭包类型
这个列表正确吗?还有其他可行的选择吗?
问题 [2]: 闭包类型只是 lambda 表达式的类型,还是在 C++ 中有其他方式创建可以被视为闭包类型的东西?
问题[3]:标准有时会谈到函数对象:问题1)列表中的什么被认为是函数对象?
问题 [4]: 执行以下操作:
- 闭包类型
- a class 使得
std::is_class_v<F>
是 true
并且 F::operator()
存在
- 一个联合使得
std::is_union_v<F>
是 true
并且 F::operator()
存在
属于标准中的特定概念(基本上是具有 operator()
的东西)?如果不是,什么是类型特征的好名字(例如,如果这样的东西在计算机科学或其他编程语言中有一个通用名称),可以检测类型是否满足列出的要点之一?
R(Args...)
、R(Args...) noexcept
、R(Args......)
和 R(Args......) noexcept
. 形式的函数类型
- (可能 cv-qualified)指向#1。
- (可能 cv-qualified) class 类型至少有一个 public
operator()
成员(包括继承);
- (可能 cv-qualified) class 类型至少有一个 public non-explicit 转换函数到 a) 参考 #1,b) #2,或c) 对#2 的引用(包括继承的);
- (可能 cv-qualified)指向成员的指针。
- 参考以上内容。
对于#3、#4 及其引用,有一个额外的条件,即类型中编码的 cv-qualification 和值类别必须与至少一个这样的函数兼容。
"Function object types" 是可以使用通常的函数调用语法调用的对象类型,即#2-#4。指向成员的指针不合格,因为您不能用 ()
.
调用它们
A "callable type" 根据定义是 "a function object types or a pointer to member",即 #2-#5.
函数类型和引用类型不是对象类型,因此既不是函数对象类型也不是可调用类型,但可以通过 std::decay
.
的应用成为一个类型
我认为您错过了
中的许多变体
- a class 这样
std::is_class_v<F>
就是 true
并且 F 继承了一个 operator()
至于闭包和 lambda,请注意 C++ 没有神奇的 lambda。 Lambda 只是 class 类型的对象,通过方便的语法创建。 std::bind
也会产生一个 Callable
对象,这也可以被认为是一个闭包。但是 "closure" 是一个在 C++ 中没有确切含义的标签,不应该出现在列表中,正如 Nicol Bolas 在评论中指出的那样。
我试图理解可以作为 std::invoke 的第一个参数传递的概念和事物类型的层次结构。
让我们考虑一种类型 F
,其中存在至少一个 Args
的组合,使得 std::is_invokable_v<F, Args...>
是 true
。
问题[1]:F
可以有哪些类型?
这是一份暂定名单:
std::function_v<F>
等函数是true
- 一个函数指针使得
std::function_v<std::remove_pointer_t<F>>
是true
- 一个函数引用使得
std::function_v<std::remove_reference_t<F>>
是true
- 对函数指针的引用使得
std::function_v<std::remove_pointer_t<std::remove_reference_t<F>>>
是true
- 指向成员函数的指针,使得
std::is_member_function_pointer_v<F>
是true
- 对指向成员函数的指针的引用使得
std::is_member_function_pointer_t<std::remove_reference_t<F>>
是true
- 指向成员对象的指针,使得
std::is_member_object_pointer_v<F>
是true
- 对指向成员对象的指针的引用使得
std::is_member_object_pointer_v<std::remove_reference_t<F>>
是true
- a class 使得
std::is_class_v<F>
是true
并且F::operator()
存在 - 对 class 的引用使得
std::is_class_v<std::remove_reference_t<F>>
是true
并且std::remove_reference_t<F>::operator()
存在 - 一个联合使得
std::is_union_v<F>
是true
并且F::operator()
存在 - 对联合的引用使得
std::is_union_v<std::remove_reference_t<F>>
是true
并且std::remove_reference_t<F>::operator()
存在 - 闭包类型
- 对闭包类型的引用使得
std::remove_reference_t<F>
是闭包类型
这个列表正确吗?还有其他可行的选择吗?
问题 [2]: 闭包类型只是 lambda 表达式的类型,还是在 C++ 中有其他方式创建可以被视为闭包类型的东西?
问题[3]:标准有时会谈到函数对象:问题1)列表中的什么被认为是函数对象?
问题 [4]: 执行以下操作:
- 闭包类型
- a class 使得
std::is_class_v<F>
是true
并且F::operator()
存在 - 一个联合使得
std::is_union_v<F>
是true
并且F::operator()
存在
属于标准中的特定概念(基本上是具有 operator()
的东西)?如果不是,什么是类型特征的好名字(例如,如果这样的东西在计算机科学或其他编程语言中有一个通用名称),可以检测类型是否满足列出的要点之一?
R(Args...)
、R(Args...) noexcept
、R(Args......)
和R(Args......) noexcept
. 形式的函数类型
- (可能 cv-qualified)指向#1。
- (可能 cv-qualified) class 类型至少有一个 public
operator()
成员(包括继承); - (可能 cv-qualified) class 类型至少有一个 public non-explicit 转换函数到 a) 参考 #1,b) #2,或c) 对#2 的引用(包括继承的);
- (可能 cv-qualified)指向成员的指针。
- 参考以上内容。
对于#3、#4 及其引用,有一个额外的条件,即类型中编码的 cv-qualification 和值类别必须与至少一个这样的函数兼容。
"Function object types" 是可以使用通常的函数调用语法调用的对象类型,即#2-#4。指向成员的指针不合格,因为您不能用 ()
.
A "callable type" 根据定义是 "a function object types or a pointer to member",即 #2-#5.
函数类型和引用类型不是对象类型,因此既不是函数对象类型也不是可调用类型,但可以通过 std::decay
.
我认为您错过了
中的许多变体- a class 这样
std::is_class_v<F>
就是true
并且 F 继承了一个operator()
至于闭包和 lambda,请注意 C++ 没有神奇的 lambda。 Lambda 只是 class 类型的对象,通过方便的语法创建。 std::bind
也会产生一个 Callable
对象,这也可以被认为是一个闭包。但是 "closure" 是一个在 C++ 中没有确切含义的标签,不应该出现在列表中,正如 Nicol Bolas 在评论中指出的那样。