C++ 是否允许类类型的std::函数成员变量(不完整类型)?

C++ 是否允许类类型的std::函数成员变量(不完整类型)?,c++,c++11,C++,C++11,我想知道这样做是否合适,它对我来说很好,但我不确定它是否真的合适: class Foo { std::function<Foo(Foo& f)> my_function; }; 不起作用我不认为(boost的一个好处是它确实适用于boost::container::vector)。确实,一般来说,使用不完整类型的参数从标准库实例化模板是无效的: [res.on.functions]/2特别是在以下情况下,效果未定义: (2.5)-如果在实例化模板组件时使用不完整类型(6

我想知道这样做是否合适,它对我来说很好,但我不确定它是否真的合适:

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

不起作用我不认为(boost的一个好处是它确实适用于
boost::container::vector
)。

确实,一般来说,使用不完整类型的参数从标准库实例化模板是无效的:

[res.on.functions]/2特别是在以下情况下,效果未定义:
(2.5)-如果在实例化模板组件时使用不完整类型(6.9)作为模板参数,除非该组件特别允许

但是,
Foo(Foo&f)
不是一个不完整的类型,即使
Foo
是:

[basic.types]/5已声明但未定义的类、某些上下文(10.2)中的枚举类型或未知绑定或不完整元素类型的数组是未完全定义的对象类型。定义不完整的对象类型和cv
void
是不完整的类型

Foo(Foo&f)
是一种函数类型。它没有列在这个定义中,所以不可能是不完整的


std::vector
特别允许使用不完整类型的参数进行实例化:

[vector.overview]/3如果分配器满足分配器完整性要求(20.5.3.5.1),则在实例化vector时可使用不完整类型
T
T
应在引用所产生的
vector
专门化的任何成员之前完成


根据标准,这似乎是好的

说:

[…]在以下情况下[效果]未定义:

  • [……]
  • 如果在实例化模板组件或评估概念时使用不完整的类型([basic.types])作为模板参数,除非该组件特别允许
但是,尽管类类型在该类的直接主体中是不完整的,但从该类类型派生的函数类型也不是不完整的(因为函数类型不是对象类型),就像指向不完整类类型的指针不是不完整的类型一样。 [func.wrap]中也没有要求
std::function
中的
R
Args
应为完整类型

或多或少,这相当于拥有一个类型为
Foo(*)(Foo&)
(指向函数的指针)的类数据成员,这也很好


您需要小心不要在类的直接主体中调用
std::function
数据成员(例如,在数据成员初始值设定项中)。(这是因为返回类prvalue的函数调用表达式在某一点上需要临时物化转换,这要求类是完整的。)在成员函数中调用它是可以的,因为
Foo
将在该点完成,甚至对于内联定义的成员函数。

实际上
vector
在c++17中也可以。Std函数不是lambda,lambda也不是Std函数。这类似于询问int,当您的代码只包含double时。您可以将lambda转换为std函数,但它们不是同一件事。您用C++11、C++14、C++17、C++20标记了它。“你问哪种标准?”CigiEN对我来说甚至适用于<代码> -STD= C++ 11 。所以它也在C++ 11中被支持,或者是那些使C++ 17在头上改变但不限制它到C++ >=17的有趣情况之一。@ CDHOWIEIRC,预C++ 17,它编译,但是是UB(或者可能是IFNDR)。但是,从c++17开始,添加了允许使用的措辞。
class Foo {
   std::vector<Foo> foos;
};