2016-06-15 55 views
6

我正在學習如何使用條件noexcept並遇到此問題。假設我有一個類:noexcept表達與類型特徵

template<typename T> 
class Wrapper { 
public: 
    Wrapper(T&& value) noexcept(/* ??? */) 
     : value_(std::move(value)) 
    {} 

private: 
    T value_; 
}; 

對於/* ??? */的一部分,我想我們可以使用noexcept(T(std::move(value)))std::is_nothrow_move_constructible<T>::value,直到我偶然發現了this

所以,如果我用noexcept(noexcept(T(std::move(value)))),嚴格來說,我認爲「此構造noexcept當且僅當構建和破壞一個Tnoexcept」?

儘管投擲的析構器應該放在火上並燒燬。

+3

你能解決這個問題嗎? 'noexcept(new T(std :: move(value)))'或someting?因爲它是一個未被評估的表達式,它實際上並沒有分配任何東西,但它也應該專門「泄漏」,因此dtor不應該參與......我想你可能需要使用新的無丟棄版本,因爲你不'要檢測'std :: bad_alloc'。 –

回答

6

好問題,另請參閱this language defect discussion。從它的名字看起來很清楚std::is_nothrow_move_constructible<T>::value應該只與來自右值的構造函數有關(但實際上也可能與破壞有關),而noexcept(T(std::move(value)))總是與構造和破壞有關。

所以,在你的情況下,最節省的方式,避免了std::is_nothrow_move_constructible性狀沒有解決的問題,就是用放置新的,避免與std::bad_alloc(克里斯·貝克的評論中提及)的問題,同樣地,使用T「 s的析構函數。

template<typename T> 
class Wrapper { 
public: 
    Wrapper(T&& value) noexcept(new(nullptr) T(std::move(value))) 
     : value_(std::move(value)) 
    {} 
    ~Wrapper() noexcept(noexcept(value_.T::~T())) 
    {} 
private: 
    T value_; 
}; 
+1

_「很明顯,std :: is_nothrow_move_constructible :: value'應該只與構造函數有關」_ - 根本不清楚,這個問題沒有解決,而且肯定不是真的,提交者的期望是正確的,或者標準中存在任何缺陷。 –

+0

@Jonathan採取了點贊。我編輯了這個問題。我認爲一個C++標準構造應該完成它所說的任務,即在這種情況下,只測試一個類型是否具有無投擲移動構造函數,而沒有別的。 – Walter

+0

但是這個特徵並不是「有沒有移動構造函數」(見[N3142](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3142.html)),爲什麼它不是那是)。相反,它會告訴你創建一個來自右值的對象是否可以拋出,這是不一樣的。對於大多數情況下,如果想要知道是否創建了它,您還想知道是否會銷燬它,因爲如果元素的析構函數可以拋出,那麼優化某個容器的內部元素就不會像元素的內部元素那樣好。 –