std::make_unique<T>需要C 17功能。可惜我必須使用C 11。當我將代碼片段移植到 時C 11,我發現了一件奇怪的事情。
使用的代碼片段make_unique效果很好:
#include <iostream>
#include <memory>
struct View;
struct Database : public std::enable_shared_from_this<Database>
{
static std::shared_ptr<Database> Create(){ return std::shared_ptr<Database>(new Database());}
std::unique_ptr<View> GetView() { return std::make_unique<View>(shared_from_this()); } //works well
~Database() {std::cout << "Database is destoryed" << std::endl;}
private:
Database(){};
};
struct View
{
std::shared_ptr<Database> db;
View(std::shared_ptr<Database> db) : db(std::move(db)) {}
~View() {std::cout << "View is destoryed" << std::endl;}
};
int main()
{
std::shared_ptr<View> view;
{
auto db{Database::Create()} ;
view = db->GetView();
}
}
而下面的代碼片段無法編譯:
#include <iostream>
#include <memory>
struct View;
struct Database : public std::enable_shared_from_this<Database>
{
static std::shared_ptr<Database> Create(){ return std::shared_ptr<Database>(new Database());}
std::unique_ptr<View> GetView() { return std::unique_ptr<View>(new View(shared_from_this())); } //here is the modification
~Database() {std::cout << "Database is destoryed" << std::endl;}
private:
Database(){};
};
struct View
{
std::shared_ptr<Database> db;
View(std::shared_ptr<Database> db) : db(std::move(db)) {}
~View() {std::cout << "View is destoryed" << std::endl;}
};
int main()
{
std::shared_ptr<View> view;
{
auto db{Database::Create()} ;
view = db->GetView();
}
}
以下是編譯器抱怨的內容:
<source>: In member function 'std::unique_ptr<View> Database::GetView()':
<source>:10:95: error: invalid use of incomplete type 'struct View'
10 | std::unique_ptr<View> GetView() { return std::unique_ptr<View>(new View(shared_from_this())); } //here is the modification
| ^
<source>:4:8: note: forward declaration of 'struct View'
4 | struct View;
| ^~~~
在我對第二個代碼片段進行了一些修改之后,這個可以作業:
#include <iostream>
#include <memory>
struct Database;
struct View
{
std::shared_ptr<Database> db;
View(std::shared_ptr<Database> db) : db(std::move(db)) {}
~View() {std::cout << "View is destoryed" << std::endl;}
};
struct Database : public std::enable_shared_from_this<Database>
{
static std::shared_ptr<Database> Create(){ return std::shared_ptr<Database>(new Database());}
#if 0
std::unique_ptr<View> GetView() { return std::make_unique<View>(shared_from_this()); } //works well
#else
std::unique_ptr<View> GetView() { return std::unique_ptr<View>(new View(shared_from_this())); }
#endif
~Database() {std::cout << "Database is destoryed" << std::endl;}
private:
Database(){};
};
int main()
{
std::shared_ptr<View> view;
{
auto db{Database::Create()} ;
view = db->GetView();
}
}
為什么 std::make_unique<View>(shared_from_this())即使對于Viewbefore的定義只有一個前向宣告,而編譯器在相同的條件下Database抱怨呢?std::unique_ptr<View>(new View(shared_from_this())
uj5u.com熱心網友回復:
為什么
std::make_unique<View>(shared_from_this())即使對于Viewbefore的定義只有一個前向宣告,而編譯器在相同的條件下Database抱怨呢?std::unique_ptr<View>(new View(shared_from_this())
考慮這個簡化的例子:
#include <memory>
struct foo;
std::unique_ptr<foo> make_foo_1() { return std::make_unique<foo>(); } // OK
std::unique_ptr<foo> make_foo_2() { return std::unique_ptr<foo>(new foo); } // ERROR
struct foo {};
In make_foo_1,std::unique_ptr<foo>被設為依賴型別,make_unique<foo>這意味著它將推遲系結到unique_ptr<foo>.
但是“在模板定義點查找和系結非依賴名稱”(即 的定義std::unique_ptr<foo>)這意味著,在 中,編譯器必須已經看到make_foo_2的定義,否則它會抱怨不完整的型別。foofoo
uj5u.com熱心網友回復:
如果有std::make_unique<View>(shared_from_this()),編譯器需要用 . 實體化函式模板template<class T, class... Args> std::unique_ptr<T> std::make_unique(Args&&...);的特化T = View, Args = {<empty>}。這發生在專業化的“實體化點”。有一個使用它(就在您呼叫時make_unique),還有一個在翻譯單元的末尾。您的編譯器碰巧在 TU 結束時實體化它(就像大多數編譯器所做的那樣),所以它恰好“作業”,但它實際上格式錯誤(因為編譯器可能在使用時實體化它會失敗)。
原因std::unique_ptr<View>(new View(shared_from_this()))不起作用是因為錯誤與運算式有關new View(shared_from_this())。沒有要處理的模板函式或實體化點,因此編譯器必須立即抱怨View不完整,正如預期的那樣。
解決方法是延遲函式的定義直到View完成:
struct View;
struct Database : public std::enable_shared_from_this<Database>
{
// ...
std::unique_ptr<View> GetView();
// ...
};
struct View
{
// ...
};
inline std::unique_ptr<View> Database::GetView()
{
// View is complete here, OK
return std::unique_ptr<View>(new View(shared_from_this()));
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/490207.html
