简体   繁体   English

是否允许使用 class 类型的 std::function 成员变量(不完整类型)?

[英]Is a std::function member variable of the class type allowed (incomplete type)?

I am wondering if this is fine to do, it compiles fine for me but I am not sure if it actually is ok:我想知道这样做是否可以,它对我来说编译得很好,但我不确定它是否真的可以:

class Foo {
  std::function<Foo(Foo& f)> my_function;
};

The function my_function takes a Foo reference and returns a Foo . function my_function接受一个Foo引用并返回一个Foo It is a member variable inside Foo , and usually these incomplete types are not allowed.它是Foo内部的成员变量,通常不允许使用这些不完整的类型。 For example:例如:

class Foo {
   std::vector<Foo> foos;
};

Would not work I don't think (a benefit of boost is that it does work for boost::container::vector ).行不通我不认为( boost 的一个好处是它确实适用于boost::container::vector )。

It is true that, in general, it is invalid to instantiate templates from the standard library with arguments that are incomplete types:确实,通常情况下,使用不完整类型的 arguments 从标准库实例化模板是无效的:

[res.on.functions]/2 In particular, the effects are undefined in the following cases: [res.on.functions]/2特别是,在以下情况下效果未定义:
(2.5) — if an incomplete type (6.9) is used as a template argument when instantiating a template component, unless specifically allowed for that component. (2.5) — 如果在实例化模板组件时将不完整类型 (6.9) 用作模板参数,除非该组件特别允许。

However, Foo(Foo& f) is not an incomplete type, even if Foo is:但是, Foo(Foo& f)不是不完整的类型,即使Foo是:

[basic.types]/5 A class that has been declared but not defined, an enumeration type in certain contexts (10.2), or an array of unknown bound or of incomplete element type, is an incompletely-defined object type . [basic.types]/5已声明但未定义的 class、某些上下文 (10.2) 中的枚举类型或未知边界或不完整元素类型的数组是未完全定义的 object 类型 Incompletely-defined object types and cv void are incomplete types...未完全定义的 object 类型和cv void是不完整类型...

Foo(Foo& f) is a function type. Foo(Foo& f)是 function 类型。 It's not listed in this definition, so cannot possibly be incomplete.它没有在这个定义中列出,所以不可能是不完整的。


std::vector is specifically allowed to be instantiated with an argument that is an incomplete type: std::vector特别允许用不完整类型的参数实例化:

[vector.overview]/3 An incomplete type T may be used when instantiating vector if the allocator satisfies the allocator completeness requirements (20.5.3.5.1). [vector.overview]/3如果分配器满足分配器完整性要求 (20.5.3.5.1),则在实例化向量时可以使用不完整类型T T shall be complete before any member of the resulting specialization of vector is referenced. T应在引用所产生的vector特化的任何成员之前完成。

Per the Standard, this appears to be fine.根据标准,这似乎很好。

[res.on.functions]/2 says: [res.on.functions]/2说:

[...] [The] effects are undefined in the following cases: [...] [The] 效果在以下情况下是不确定的:

  • [...] [...]
  • If an incomplete type ([basic.types]) is used as a template argument when instantiating a template component or evaluating a concept, unless specifically allowed for that component.如果在实例化模板组件或评估概念时将不完整的类型 ([basic.types]) 用作模板参数,除非该组件特别允许。

But while a class type is incomplete within the immediate body of that class, a function type derived from that class type is not incomplete (since a function type is not an object type), much as a pointer to an incomplete class type is not an incomplete type. But while a class type is incomplete within the immediate body of that class, a function type derived from that class type is not incomplete (since a function type is not an object type), much as a pointer to an incomplete class type is not an不完整的类型。 There are also no requirements within [func.wrap] that R or Args in std::function<R(Args...)> should be complete types. [func.wrap] 中也没有要求Rstd::function<R(Args...)> Args的 Args 应该是完整类型。

More or less, this is equivalent to having a class data member of type Foo(*)(Foo&) (pointer to function), which is also fine.或多或少,这相当于拥有一个Foo(*)(Foo&)类型的 class 数据成员(指向函数的指针),这也很好。

You will need to be careful not to call the std::function data member within the immediate body of your class (eg in a data member initializer).您需要注意不要在 class 的直接主体中调用std::function数据成员(例如,在数据成员初始化程序中)。 (This is because a function call expression that returns an class prvalue will at some point require a temporary materialization conversion, which requires the class to be complete.) Calling it within member functions is fine, since Foo will be complete by that point, even for member functions defined inline. (这是因为返回 class prvalue 的 function 调用表达式在某些时候需要临时实现转换,这需要Foo是完整的。)对于内联定义的成员函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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