以下代码无法编译:
#include <functional>
struct X
{
std::function<X()> _gen;
};
int main()
{
X x;
x._gen = [] { return X(); }; //this line is causing problem!
}
我不明白为什么分配给 x._gen
会导致问题。两个gcc和 clang正在给出类似的错误消息。谁能解释一下?
编译器错误信息
In file included from main.cpp:1:0:
/usr/include/c++/4.8/functional: In instantiation of ‘std::function<_Res(_ArgTypes ...)>::_Requires<std::function<_Res(_ArgTypes ...)>::_CheckResult<std::function<_Res(_ArgTypes ...)>::_Invoke<_Functor>, _Res>, std::function<_Res(_ArgTypes ...)>&> std::function<_Res(_ArgTypes ...)>::operator=(_Functor&&) [with _Functor = main()::__lambda0; _Res = X; _ArgTypes = {}; std::function<_Res(_ArgTypes ...)>::_Requires<std::function<_Res(_ArgTypes ...)>::_CheckResult<std::function<_Res(_ArgTypes ...)>::_Invoke<_Functor>, _Res>, std::function<_Res(_ArgTypes ...)>&> = std::function<X()>&]’:
main.cpp:11:12: required from here
/usr/include/c++/4.8/functional:2333:4: error: no matching function for call to ‘std::function<X()>::function(main()::__lambda0)’
function(std::forward<_Functor>(__f)).swap(*this);
^
/usr/include/c++/4.8/functional:2333:4: note: candidates are:
/usr/include/c++/4.8/functional:2255:2: note: template<class _Functor, class> std::function<_Res(_ArgTypes ...)>::function(_Functor)
function(_Functor);
^
/usr/include/c++/4.8/functional:2255:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/functional:2230:7: note: std::function<_Res(_ArgTypes ...)>::function(std::function<_Res(_ArgTypes ...)>&&) [with _Res = X; _ArgTypes = {}]
function(function&& __x) : _Function_base()
^
/usr/include/c++/4.8/functional:2230:7: note: no known conversion for argument 1 from ‘main()::__lambda0’ to ‘std::function<X()>&&’
/usr/include/c++/4.8/functional:2433:5: note: std::function<_Res(_ArgTypes ...)>::function(const std::function<_Res(_ArgTypes ...)>&) [with _Res = X; _ArgTypes = {}]
function<_Res(_ArgTypes...)>::
^
/usr/include/c++/4.8/functional:2433:5: note: no known conversion for argument 1 from ‘main()::__lambda0’ to ‘const std::function<X()>&’
/usr/include/c++/4.8/functional:2210:7: note: std::function<_Res(_ArgTypes ...)>::function(std::nullptr_t) [with _Res = X; _ArgTypes = {}; std::nullptr_t = std::nullptr_t]
function(nullptr_t) noexcept
^
/usr/include/c++/4.8/functional:2210:7: note: no known conversion for argument 1 from ‘main()::__lambda0’ to ‘std::nullptr_t’
/usr/include/c++/4.8/functional:2203:7: note: std::function<_Res(_ArgTypes ...)>::function() [with _Res = X; _ArgTypes = {}]
function() noexcept
^
/usr/include/c++/4.8/functional:2203:7: note: candidate expects 0 arguments, 1 provided
同样,Clang throws这个:
main.cpp:11:12: error: no viable overloaded '='
x._gen = [] { return X(); };
~~~~~~ ^ ~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:2270:7: note: candidate function not viable: no known conversion from '<lambda at main.cpp:11:14>' to 'const std::function<X ()>' for 1st argument
operator=(const function& __x)
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:2288:7: note: candidate function not viable: no known conversion from '<lambda at main.cpp:11:14>' to 'std::function<X ()>' for 1st argument
operator=(function&& __x)
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:2302:7: note: candidate function not viable: no known conversion from '<lambda at main.cpp:11:14>' to 'nullptr_t' for 1st argument
operator=(nullptr_t)
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:2192:39: note: candidate template ignored: disabled by 'enable_if' [with _Functor = <lambda at main.cpp:11:14>]
using _Requires = typename enable_if<_Cond::value, _Tp>::type;
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:2340:2: note: candidate template ignored: could not match 'reference_wrapper<type-parameter-0-0>' against '<lambda at main.cpp:11:14>'
operator=(reference_wrapper<_Functor> __f) noexcept
^
最佳答案
这是 PR60594 ,在 GCC 4.8.3 中得到修复。对该错误的评论指出了它为什么有效:尽管标准要求标准库模板的模板参数是完整类型(有一些异常(exception)),X()
是一个完整的类型,即使 X
不是。
std::function<X()>
有几个成员确实需要X
成为一个完整的类型。您正在使用的模板构造函数就是其中之一:它要求您的 lambda 的返回类型可以隐式转换为 X
, 但是否 X
是否可转换为自身取决于 X
是完整类型:如果不完整,编译器不能排除它是不可复制不可移动类型的可能性。
此要求来自:
20.9.11.2.1 function construct/copy/destroy [func.wrap.func.con]
8 Remarks: These constructors shall not participate in overload resolution unless
f
is Callable (20.9.11.2) for argument typesArgTypes...
and return typeR
.20.9.11.2 Class template function [func.wrap.func]
2 A callable object
f
of typeF
is Callable for argument typesArgTypes
and return typeR
if the expressionINVOKE
(f, declval<ArgTypes>()..., R)
, considered as an unevaluated operand (Clause 5), is well formed (20.9.2).20.9.2 Requirements [func.require]
2 Define
INVOKE
(f, t1, t2, ..., tN, R)
asINVOKE
(f, t1, t2, ..., tN)
implicitly converted toR
.
std::function
的其他几个成员还需要X
成为一个完整的类型。
你只是在类型X
之后使用那个构造函数不过已经完成了,所以没有问题:此时,X
当然可以隐式转换为X
.
问题是 std::function
正在执行依赖于 X
的检查作为一个完整类型,在标准不支持执行此类检查的情况下,这并没有考虑到 X
的可能性。 std::function<X()>
实例化后将成为完整类型已经完成了。
关于c++ - 当 std::function<X()> 是 X 类的成员时,为什么不能编译它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20129601/