2013-07-06 58 views
13

看看下面的例子,我們解析數據,並將結果傳遞到下一個功能移動:如何從標準::可選<T>

Content Parse(const std::string& data); 
void Process(Content content); 

int main() 
{ 
    auto data = ReadData(); 
    Process(Parse(data));  
} 

現在讓我們用std::optional處理失敗的分析步驟中更改代碼:

optional<Content> Parse(const std::string& data); 
void Process(Content content); 

int main() 
{ 
    auto data = ReadData(); 
    auto content = Parse(data); 
    if (content) 
     Process(move(*content)); 
} 

是否有效從optional<T>::value()移動?如果std::optional可以,那麼它是否也適用於boost::optional

+0

我會認爲這會很好。包含的值在移動後應該處於有效但未指定的狀態。 –

回答

9

optional<T>::value()開始移動是有效的,因爲它返回一個可變引用,並且該移動不會破壞該對象。如果optional實例不是從事,value()將拋出bad_optional_access異常(第20.6.4.5節)。

你明確檢查選項是否從事:

if (content) 
    Process(move(*content)); 

但你不使用成員value()訪問底層T。請注意,value()在返回有效的T&之前執行內部檢查,而不像operator*其中有前提條件optional實例應該從事。這是一個微妙的差異,但你使用正確的成語:

if (o) 
    f(*o) 

,而不是

if (o) // redundant check 
    f(o.value()) 

在加速,情況稍有不同:第一,不存在所謂的value()成員函數提供檢查訪問。 (A bad_optional_access異常根本不存在)。成員get()只是operator*的別名,並且始終依賴於用戶檢查optional實例的參與。

+0

'operator *'是否有右值引用超載?即,'f(* std :: move(o))' - 是否會移動?但願如此! – Yakk

+0

我在[標準]中找不到一個(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf)。請參閱第505頁的第20.6.4節,其中介紹了接口。 – mavam

+1

嗯。 'value_or'有一個'&&'和'&'重載。 「價值」不(爲什麼不呢?天真的,它應該)。我可以看到,如果沒有檢查'optional'是否首先被使用,而'throw'value'我看不到'傷害',那麼我們可以看到'''&&''operator * – Yakk