简体   繁体   English

std :: move_if_noexcept的基本原理仍在移动投掷仅移动类型?

[英]Rationale for std::move_if_noexcept still moving throwing move-only types?

move_if_noexcept will: move_if_noexcept将:

  • return an rvalue -- facilitating a move -- if the move constructor is noexcept or if there is no copy constructor (move-only type) 返回一个rvalue - 促进移动 - 如果移动构造函数是noexcept 或者没有复制构造函数(仅移动类型)
  • return an lvalue -- forcing a copy -- otherwise 返回一个左值 - 强制复制 - 否则

I found this rather surprising, as a move-only type that has a throwing move-ctor will still have this move-ctor invoked by code that uses move_if_noexcept . 我发现这个相当令人惊讶,因为只有移动类型的投掷移动器仍然会使用move_if_noexcept的代码调用此移动move_if_noexcept

Has there been given a thorough rationale for this? 有没有给出一个彻底的理由呢? (Maybe directly or between the lines of N2983 ?) (可能直接或在N2983之间?)

Wouldn't code be better off not compiling rather than still having to face the unrecoverable move scenario? 不编码会不会更好,而不是仍然不得不面对不可恢复的移动场景? The vector example given in N2983 is nice: N2983中给出的vector示例很好:

void reserve(size_type n)
{
  ... ...
                 new ((void*)(new_begin + i)) value_type( std::move_if_noexcept( (*this)[i]) ) );
        }
        catch(...)
        {
            while (i > 0)                 // clean up new elements
               (new_begin + --i)->~value_type();

            this->deallocate( new_begin );    // release storage
            throw;
        }
*!*     // -------- irreversible mutation starts here -----------
        this->deallocate( this->begin_ );
        this->begin_ = new_begin;
        ... ...

The comment given in the marked line is actually wrong - for move-only types that can throw on move construction, the - possibly failing - irreversible mutation actually already starts when we move the old elements into their new positions. 标记线中给出的注释实际上是错误的 - 对于可以投掷移动构造的仅移动类型,当我们将旧元素移动到新位置时,实际上已经开始 - 可能失败 - 不可逆转的突变。

Looking at it briefly, I'd say that a throwing move-only type couldn't be put into a vector otherwise, but maybe it shouldn't? 简要地看一下,我会说投掷移动的类型不能放入矢量中,否则它可能不应该?

Looking at it briefly, I'd say that a throwing move-only type couldn't be put into a vector otherwise, but maybe it shouldn't? 简要地看一下,我会说投掷移动的类型不能放入矢量中,否则它可能不应该?

I believe you've nicely summed up the choices the committee had for containers of move-only-noexcept(false)-types. 我相信你已经很好地总结了委员会对于仅移动 - 禁止(假) - 类型的容器的选择。

  1. Allow them but with basic exception safety instead of strong for some operations. 允许它们但具有基本的异常安全性,而不是强大的某些操作。
  2. Disallow them at compile time. 在编译时禁止它们。

A. The committee absolutely felt that they could not silently change existing C++03 code from having the strong exception safety to having basic exception safety. 答:委员会绝对认为他们无法默默地将现有的C ++ 03代码从具有强大的异常安全性转变为具有基本的异常安全性。

B. For those functions that have strong exception safety, the committee much preferred to have those members continue to have strong exception safety, even for code that could not possibly be written yet (eg for functions manipulating move-only types). B.对于具有强大异常安全性的那些函数,委员会更倾向于使这些成员继续具有强大的异常安全性,即使对于尚不可能编写的代码(例如,用于操作仅移动类型的函数)。

The committee realized it could accomplish both of the objectives above, except for the case in B) where the move-only type might throw during move construction. 委员会意识到它可以完成上述两个目标,但B)中的情况除外,其中只有移动类型可能在移动施工期间抛出。 These cases are limited to a few member functions of vector IIRC: push_back , reserve . 这些情况仅限于vector IIRC的几个成员函数: push_backreserve Note that other members of vector already offer only basic exception safety (even in C++98/03), eg: assignment, insert (unless inserting at the end), erase. 注意, vector其他成员已经只提供了基本的异常安全性(即使在C ++ 98/03中),例如:赋值,插入(除非在末尾插入),擦除。

With all this in mind, it was the committee's decision that should the client create a vector of a move-only-noexcept(false)-type, it would be more useful to the client to relax the strong exception safety to basic (as it already is for other vector members), rather than to refuse to compile. 考虑到所有这些,委员会的决定应该是客户创建一个只移动 - 无法(错误)类型的vector ,对于客户来说,将基本的强大异常安全性放松是更有用的(因为它已经是为了其他向量成员),而不是拒绝编译。

This would only be new code that the client writes for C++11, not legacy code, since move-only types do not exist prior to C++11. 这只是客户端为C ++ 11编写的新代码,而不是遗留代码,因为在C ++ 11之前不存在仅移动类型。 And no doubt the educators of C++11 should be encouraging their students to write noexcept(true) move members. 毫无疑问,C ++ 11的教育工作者应该鼓励他们的学生编写noexcept(真正的)移动成员。 However code with the basic exception safety guarantee is not so dangerous, nor unusual, such that it should be forbidden. 但是,具有基本异常安全保证的代码不是那么危险,也不是不寻常的,因此应该禁止它。 After all, the std::lib is already chock full of code carrying only the basic exception safety guarantee. 毕竟,std :: lib已经充满了只带有基本异常安全保证的代码。

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

相关问题 std :: move_if_noexcept调用copy-assignment,即使move-assignment是noexcept; 为什么? - std::move_if_noexcept calls copy-assignment even though move-assignment is noexcept; why? 为什么在C ++ 11/14中没有std :: move_if_noexcept对应std :: forward? - Why there is no std::move_if_noexcept counterpart for std::forward in C++11/14? std::function 的仅移动版本 - Move-only version of std::function 处理包含只移动类型的变体 - dealing with variants containing move-only types 禁用异常支持是否也禁用对`std :: move_if_noexcept`的支持? - Does disabling support for exceptions also disable support for `std::move_if_noexcept`? std::bind 是否适用于一般只移动类型,特别是 std::unique_ptr ? - Does std::bind work with move-only types in general, and std::unique_ptr in particular? 如何通过值传递仅移动类型(例如std :: unique_ptr)? - How is it possible to pass move-only types (e.g. std::unique_ptr) by value? 在成员容器中使用仅移动但可克隆类型的复制构造函数 - Copy constructors with move-only, but cloneable types in member containers boost :: variant处理仅移动类型的奇怪行为 - Strange behavior in boost::variant's handling of move-only types 为什么 extern 模板实例化不适用于仅移动类型? - Why does extern template instantiation not work on move-only types?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM