簡體   English   中英

std :: move_if_noexcept的基本原理仍在移動投擲僅移動類型?

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

move_if_noexcept將:

  • 返回一個rvalue - 促進移動 - 如果移動構造函數是noexcept 或者沒有復制構造函數(僅移動類型)
  • 返回一個左值 - 強制復制 - 否則

我發現這個相當令人驚訝,因為只有移動類型的投擲移動器仍然會使用move_if_noexcept的代碼調用此移動move_if_noexcept

有沒有給出一個徹底的理由呢? (可能直接或在N2983之間?)

不編碼會不會更好,而不是仍然不得不面對不可恢復的移動場景? 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;
        ... ...

標記線中給出的注釋實際上是錯誤的 - 對於可以投擲移動構造的僅移動類型,當我們將舊元素移動到新位置時,實際上已經開始 - 可能失敗 - 不可逆轉的突變。

簡要地看一下,我會說投擲移動的類型不能放入矢量中,否則它可能不應該?

簡要地看一下,我會說投擲移動的類型不能放入矢量中,否則它可能不應該?

我相信你已經很好地總結了委員會對於僅移動 - 禁止(假) - 類型的容器的選擇。

  1. 允許它們但具有基本的異常安全性,而不是強大的某些操作。
  2. 在編譯時禁止它們。

答:委員會絕對認為他們無法默默地將現有的C ++ 03代碼從具有強大的異常安全性轉變為具有基本的異常安全性。

B.對於具有強大異常安全性的那些函數,委員會更傾向於使這些成員繼續具有強大的異常安全性,即使對於尚不可能編寫的代碼(例如,用於操作僅移動類型的函數)。

委員會意識到它可以完成上述兩個目標,但B)中的情況除外,其中只有移動類型可能在移動施工期間拋出。 這些情況僅限於vector IIRC的幾個成員函數: push_backreserve 注意, vector其他成員已經只提供了基本的異常安全性(即使在C ++ 98/03中),例如:賦值,插入(除非在末尾插入),擦除。

考慮到所有這些,委員會的決定應該是客戶創建一個只移動 - 無法(錯誤)類型的vector ,對於客戶來說,將基本的強大異常安全性放松是更有用的(因為它已經是為了其他向量成員),而不是拒絕編譯。

這只是客戶端為C ++ 11編寫的新代碼,而不是遺留代碼,因為在C ++ 11之前不存在僅移動類型。 毫無疑問,C ++ 11的教育工作者應該鼓勵他們的學生編寫noexcept(真正的)移動成員。 但是,具有基本異常安全保證的代碼不是那么危險,也不是不尋常的,因此應該禁止它。 畢竟,std :: lib已經充滿了只帶有基本異常安全保證的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM