Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么分配给std::function<;X()>;不';当它是类X的成员时,是否编译?_C++_C++11_Lambda_Std Function - Fatal编程技术网

C++ 为什么分配给std::function<;X()>;不';当它是类X的成员时,是否编译?

C++ 为什么分配给std::function<;X()>;不';当它是类X的成员时,是否编译?,c++,c++11,lambda,std-function,C++,C++11,Lambda,Std Function,以下代码未编译: #include <functional> struct X { std::function<X()> _gen; }; int main() { X x; x._gen = [] { return X(); }; //this line is causing problem! } 同样,这: main.cpp:11:12:错误:没有可行的重载'=' x、 _gen=[]{return x();}; ~~~~~~ ^ ~~~

以下代码未编译:

#include <functional>

struct X
{
    std::function<X()> _gen;
};

int main()
{
    X x;
    x._gen = [] { return X(); }; //this line is causing problem!
}
同样,这:

main.cpp:11:12:错误:没有可行的重载'='
x、 _gen=[]{return x();};
~~~~~~ ^ ~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/functional:2270:7:注意:候选函数不可行:第一个参数没有从“”到“const std::function”的已知转换
运算符=(常量函数&x)
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/functional:2288:7:注意:候选函数不可行:第一个参数没有从“”到“std::function”的已知转换
运算符=(函数&&&ux)
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/functional:2302:7:注意:候选函数不可行:第一个参数没有从“”到“nullptr_t”的已知转换
运算符=(nullptr\u t)
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/functional:2192:39:注意:忽略候选模板:由“如果启用”禁用[使用_Functor=]
使用_Requires=typename enable_if::type;
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/functional:2340:2:注意:已忽略候选模板:无法与“”匹配“引用\u包装器”
运算符=(引用包装器)无异常
^

这可能是一个gcc错误,但可能不是。它不是直接在
=
中,而是在
std::function
的转换构造函数中(由
操作符=
调用)

这是一个病理学上的例子:

#include <iostream>
#include <functional>

struct X
{
  std::function<X()> _gen;
};

X func() {return {};};

int main()
{
  std::function<X()> foo1( &func ); // compiles
  X unused = X{}; // copy ctor invoked
  std::function<X()> foo2( &func ); // does not compile!
}
该复制构造函数最终调用
\u gen
的复制构造函数,可能是在
X
是完整类型之前

如果我们显式延迟
X::X(X const&)
的实例化,直到
X
是一个完整类型:

#include <functional>

struct X
{
  std::function<X()> _gen;
  X( X const& );
  X() {}
};
X::X( X const& o ):_gen(o._gen){} // or =default *here*

X func() {return {};};

int main()
{
  std::function<X()> foo1( &func ); // compiles!
  []{ return X{}; }; // or X unused = X{};
  std::function<X()> foo2( &func ); // compiles!
}
#包括
结构X
{
标准::功能_gen;
X(X常数&);
X(){}
};
X::X(X常量&o):\u gen(o.\u gen){}//or=default*此处*
X func(){return{};};
int main()
{
std::函数foo1(&func);//编译!
[]返回X{};};//或X未使用=X{};
std::函数foo2(&func);//编译!
}
问题消失了

我怀疑当
X
是不完整类型时,在
X
的主体中创建的
X
的隐式复制构造函数隐式调用了
std::function
的复制构造函数,该构造函数位于
X
不完整的上下文中,这打破了调用其复制构造函数的先决条件(至少在实践中,它是如何在gcc中实现的——按照标准?我不确定。)

通过显式地在
X
之外创建一个拷贝,我避免了这种情况,并且一切正常

因此,作为解决问题的方法,声明并实现
X::X(X const&)
X
之外,神奇的错误消失了。

这是一个错误,在GCC 4.8.3中得到了修复。对该错误的评论指出了它有效的原因:尽管标准要求标准库模板的模板参数是完整类型(除了一些例外),
X()
是完整类型,即使
X
不是

std::function
的多个成员确实隐式要求
X
为完整类型。您使用的模板构造函数就是其中之一:它要求lambda的返回类型隐式转换为
X
,但
X
是否可转换为自身取决于
X
是一个完整类型:如果它不完整,编译器不能排除它是不可压缩不可移动类型的可能性

这项要求来自:

20.9.11.2.1函数构造/复制/销毁[func.wrap.func.con]

8备注:除非参数类型
ArgTypes…
和返回类型
R
可调用
f
(20.9.11.2),否则这些构造函数不得参与重载解析

20.9.11.2类模板函数[func.wrap.func]

2如果表达式
调用
(f,declval()…,R)
被视为未赋值的操作数(第5条),则类型为
f
的可调用对象
f
可调用参数类型
ArgTypes
,返回类型为
R
(第20.9.2条)

20.9.2要求[功能要求]

2将
调用
(f,t1,t2,…,tN,R)
定义为
调用
(f,t1,t2,…,tN)
隐式转换为
R

std::function
的其他几个成员也要求
X
为完整类型

但是,只有在类型
X
已经完成之后才使用该构造函数,因此没有问题:在这一点上,
X
当然可以隐式转换为
X


问题在于,
std::function
执行的检查依赖于
X
是一个完整的类型,在标准不支持执行此类检查的情况下,这并没有考虑到
std::function
实例化后,
X
将成为一个完整类型的可能性VisualStudio 2012接受了这个代码。@ Duffic:如果它是编译器错误,那么很有意思的是Visual C++这次是正确的。我的CLAN接受它。我想问题是:可以<代码> STD::函数< /C> >用不完整的类型声明。@ ZCH不,它不是明确允许的。但是我不是S。如果
X()
是一个不完整的类型,@zch:我找不到任何理由不能用不完整的类型声明它:它不存储类类型的数据。而且,
X()
就我的理由而言不是一个不完整的类型。g++4.8.1在排除lambda(即第二个lambda)时也不会编译它
#include <iostream>
#include <functional>

struct X
{
  std::function<X()> _gen;
};

X func() {return {};};

int main()
{
  std::function<X()> foo1( &func ); // compiles
  X unused = X{}; // copy ctor invoked
  std::function<X()> foo2( &func ); // does not compile!
}
#include <iostream>
#include <functional>

struct X
{
  std::function<X()> _gen;
  X( X const& ) = default;
  X() = default;
};
X func() {return {};};

int main()
{
  std::function<X()> foo1( &func ); // does not compile
}
#include <functional>

struct X
{
  std::function<X()> _gen;
  X( X const& );
  X() {}
};
X::X( X const& o ):_gen(o._gen){} // or =default *here*

X func() {return {};};

int main()
{
  std::function<X()> foo1( &func ); // compiles!
  []{ return X{}; }; // or X unused = X{};
  std::function<X()> foo2( &func ); // compiles!
}