[英]polymorphic unique_ptr copy elision
我有以下代碼適用於Clang 5.0但不適用於Clang 3.8,啟用了C ++ 14:
class Base {};
class Derived : public Base {};
std::unique_ptr<Base> MakeDerived()
{
auto derived = std::make_unique<Derived>();
return derived;
}
int main()
{
auto base = MakeDerived();
std::cout << "Type: " << typeid(base).name() << '\n';
}
在這種情況下,由於復制省略,返回值在技術上是移動構造的嗎? 如果是這樣,這是否意味着unique_ptr
的移動構造函數旨在支持用戶類類型的隱式向上轉換? 從cppreference文檔 (#6)中很難說,除非我在該文檔頁面上假設模板類型U
與類本身的類型T
明顯不同。
顯而易見的一件事就是unique_ptr
不是可復制構造的,因為我沒有通過std::move()
將它轉換為rvalue,所以沒有其他解釋為什么代碼會編譯而不是復制省音。 但是因為它不適用於接受-std=c++14
標志的clang 3.8,我想確保標准本身保證某個地方(如果是這樣,哪里),這只是一個編譯器錯誤或缺乏支持問題在Clang的v3.8中。
復制省略(在C ++ 17之前)總是要求省略的構造函數實際可訪問,因此它不能成為代碼工作的原因。
但請注意,C ++(自C ++ 11以來)有一個規則(12.8 / 32),歸結為以下內容:“在返回對象時,在某些情況下,首先嘗試將對象視為右值,並且僅在失敗了,把它當作左值。“
在C ++ 11中,這些“特定情況”是“復制省略是可能的”,這要求返回的對象和返回類型是相同的類型(模數cv限定)。
在C ++ 14中,這些“特定情況”被放寬為“可以復制省略,或者返回的對象是函數中的局部變量”。
因此,在C ++ 11,代碼失敗,因為std::unique_ptr<Derived>
(類型derived
)為不同std::unique_ptr<Base>
(返回類型),等等std::move
將不得不使用。
在C ++ 14中,代碼成功,因為derived
是函數中的局部函數,因此首先將其視為rvalue。 這使您引用的構造函數模板適用:
如果U*
可以轉換為T*
則std::unique_ptr<T>
可以從std::unique_ptr<U>
類型的右值構造。
您的Clang 3.8似乎表現出C ++ 11的行為; 或許它(尚未完全)在該版本中實現了C ++ 14的輕松方面。
(是的,確實你應該假設“模板類型” U
與類的模板參數T
。這就是它首先被引入的原因:#6描述的構造函數是構造函數模板 )。
該return
調用unique_ptr
的轉換移動構造函數模板, template<class U, class E> unique_ptr(unique_ptr<U, E>&&)
。 沒有任何缺點; 它取決於核心問題1579解決方案對derived
的隱含移動。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.