在C ++中被认为是可调用的类型是什么?

时间:2018-03-27 01:01:08

标签: c++ lambda c++17 functor typetraits

我试图理解可以作为std :: invoke的第一个参数传递的概念和事物类型的层次结构。

我们考虑使用F类型,以便至少存在Args的{​​{1}}组合,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
  • 一个类,std::is_class_v<F>trueF::operator()存在
  • 对类的引用,std::is_class_v<std::remove_reference_t<F>>truestd::remove_reference_t<F>::operator()存在
  • 一个联盟,std::is_union_v<F>trueF::operator()存在
  • 对联盟的引用,std::is_union_v<std::remove_reference_t<F>>truestd::remove_reference_t<F>::operator()存在
  • 封闭类型
  • 对闭包类型的引用,使std::remove_reference_t<F>为闭包类型

此列表是否正确?还有其他可行的选择吗?

问题[2]:闭包类型只是lambda表达式的类型,还是在C ++中有其他方式来创建一些被视为闭包类型的东西?

问题[3]:标准有时会讨论函数对象:问题1列表中的内容被视为函数对象?

问题[4]:执行以下操作:

  • 封闭类型
  • 一个类,std::is_class_v<F>trueF::operator()存在
  • 一个联盟,std::is_union_v<F>trueF::operator()存在

属于标准中的特定概念(基本上是具有operator()的东西)?如果不是,那么一个好的名称(例如,如果这样的东西在计算机科学或其他编程语言中有一个共同的名称)对于一个类型特征会检测一个类型是否满足列出的一个项目点?

2 个答案:

答案 0 :(得分:3)

  1. 表单R(Args...)R(Args...) noexceptR(Args......)R(Args......) noexcept的函数类型。
  2. (可能是cv认证的)指向#1。
  3. (可能是cv-qualified)具有至少一个公共operator()成员(包括继承)的类类型;
  4. (可能是cv限定的)具有至少一个公共非显式转换函数的类类型,a)引用#1,b)#2,或c)引用#2(包括继承);
  5. (可能是cv-qualified)指向成员的指针。
  6. 参考上文。
  7. 对于#3,#4及其引用,还有一个额外的限定条件,即该类型中编码的cv资格和值类别必须与至少一个这样的函数兼容。

    "Function object types"是可以使用通常的函数调用语法调用的对象类型,即#2-#4。指向成员的指针不符合条件,因为您无法使用()调用它们。

    根据定义,"callable type"是&#34;函数对象类型或指向成员的指针&#34;,即#2-#5。

    函数类型和引用类型不是对象类型,因此既不是函数对象类型也不是可调用类型,但可以成为std::decay应用程序的类型。

答案 1 :(得分:0)

我认为你错过了

的许多变化
  • 一个类,std::is_class_v<F>true,并且F继承operator()

至于闭包和lambda,请注意C ++没有神奇的lambda。 Lambda只是类类型的对象,通过方便的语法创建。 std::bind也会产生一个Callable对象,这也可以被认为是一个闭包。但是,“封闭”是一个在C ++中没有确切含义的标签,不应该在列表中,正如Nicol Bolas在评论中所指出的那样。