在C ++ 11中使用std :: move使用统一的初始化语法移动构造函数 [英] Use std::move in C++11 move constructor with uniform initialization syntax

查看:175
本文介绍了在C ++ 11中使用std :: move使用统一的初始化语法移动构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个简单的类:

  struct Worker 
{
Worker false} {}
Worker(const Worker& rhs):done {rhs.done},qworker {} {}
Worker(Worker&& rhs):done {rhs.done}
{
qworker = std :: move(rhs.qworker);
}
...
}

gcc-4.7.2但如果我尝试使用这个版本,我得到一个错误

  struct Worker 
{
Worker():done {false} {}
Worker(const Worker& rhs):done {rhs.done},qworker {} {}
Worker done {rhs.done}
,qworker {std :: move(rhs.qworker)} //< - ERROR
{
}
...
}

为什么?

 在tlog.cpp中包含的文件中:8:0:
log11.hpp:在成员函数'void Log11 :: Worker :: run()':
log11.hpp: 34:29:error:'class std :: vector< std :: function< void()> >'没有名为'pop_front'的成员
在/usr/include/c++/4.7/thread:39:0中包含的文件中,
来自tlog.cpp:3:
/ usr /include/c++/4.7/functional:在实例化'static void std :: _ Function_handler< void(_ArgTypes ...),_Functor> :: _ M_invoke(const std :: _ Any_data& _ArgTypes ...)[with _Functor = std :: vector< std :: function< void()> > ;; _ArgTypes = {}]':
/usr/include/c++/4.7/functional:2298:6:需要从'std :: function< _Res(_ArgTypes ...)> :: function(_Functor,typename std :: enable_if<(!std :: is_integral< _Functor> :: value),std :: function< _Res(_ArgTypes ...)> :: _ Useless> :: type)[with _Functor = std :: vector& std :: function< void()> > ;; _Res = void; _ArgTypes = {}; typename std :: enable_if<(!std :: is_integral< _Functor> :: value),std :: function< _Res(_ArgTypes ...)> :: _ Useless> :: type = std :: function< void > :: _ Useless]'
log11.hpp:20:78:从这里需要
/usr/include/c++/4.7/functional:1926:2:错误:没有匹配到调用' std :: vector< std :: function< void()>>)(


解决方案

根据C ++ 11标准 std :: function 有一个不受约束的构造函数模板接受任何参数类型:

 模板< class F>函数(F f); 

当你说 qworker {std :: move(rhs.qworker)} 这首先尝试调用 std :: initializer_list< std :: function< void()>> 的构造函数。由于上面显示的非约束构造函数模板,可以从任何类型构造 std :: function initializer_list ,如下所示:

  {std :: function< void()> {std :: move(rhs.qworker)}} 

无效,因为 rhs.qworker 不是一个可调用的对象,但只有当你尝试调用函数对象时才会发生错误。



如果你说 qworker(std :: move(rhs.qworker))那么初始化列表构造函数不是候选项,而是调用move构造函数。 / p>

有一个针对标准的缺陷报告( LWG 2132 ),通过阻止函数(F)构造函数模板被调用来解决这个问题,除非参数是一个可调用的对象。这阻止了创建 initializer_list< function< void()>> ,而是 qworker {std :: move(rhs.qworker)} 按预期调用move构造函数。 GCC 4.7没有实现LWG 2132的解决方案,但GCC 4.8。


I have this simple class:

struct Worker
{
        Worker() : done{false} {}
        Worker(const Worker& rhs) : done{rhs.done}, qworker{} {}
        Worker(Worker &&rhs) : done{rhs.done}
        {
            qworker = std::move(rhs.qworker);
        }
...
}

this compile fine with gcc-4.7.2 but if I try to use this version I obtain an error

struct Worker
{
        Worker() : done{false} {}
        Worker(const Worker& rhs) : done{rhs.done}, qworker{} {}
        Worker(Worker &&rhs) : done{rhs.done}
                             , qworker{std::move(rhs.qworker)} // <- ERROR
        {
        }
...
}

Why?

In file included from tlog.cpp:8:0:
log11.hpp: In member function ‘void Log11::Worker::run()’:
log11.hpp:34:29: error: ‘class std::vector<std::function<void()> >’ has no member named ‘pop_front’
In file included from /usr/include/c++/4.7/thread:39:0,
                 from tlog.cpp:3:
/usr/include/c++/4.7/functional: In instantiation of ‘static void std::_Function_handler<void(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Functor = std::vector<std::function<void()> >; _ArgTypes = {}]’:
/usr/include/c++/4.7/functional:2298:6:   required from ‘std::function<_Res(_ArgTypes ...)>::function(_Functor, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type) [with _Functor = std::vector<std::function<void()> >; _Res = void; _ArgTypes = {}; typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type = std::function<void()>::_Useless]’
log11.hpp:20:78:   required from here
/usr/include/c++/4.7/functional:1926:2: error: no match for call to ‘(std::vector<std::function<void()> >) ()’

解决方案

According to the C++11 standard std::function has an unconstrained constructor template that accepts any argument type:

template<class F> function(F f);

When you say qworker{std::move(rhs.qworker)} this first attempts to call a constructor taking std::initializer_list<std::function<void()>>. Because of the unconstrained constructor template shown above, a std::function<void()> can be constructed from any type, so you get an initializer_list with one member, like this:

{ std::function<void()>{std::move(rhs.qworker)} }

This is invalid, because rhs.qworker is not a callable object, but the error only happens when you try to invoke the function objects.

If you say qworker(std::move(rhs.qworker)) then the initializer list constructor is not a candidate and the move constructor is called instead.

There is a defect report against the standard (LWG 2132) which fixes this by preventing the function(F) constructor template being called unless the argument is a callable object. That prevents an initializer_list<function<void()>> being created, and instead qworker{std::move(rhs.qworker)} calls the move constructor, as intended. GCC 4.7 does not implement the resolution for LWG 2132, but GCC 4.8 does.

这篇关于在C ++ 11中使用std :: move使用统一的初始化语法移动构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆