“ std :: make_unique”和`sTD :: simel_ptr`与正向声明之间的奇怪行为
std :: make_unique< t>
需求c ++ 17
feature.t poth,我必须使用c ++ 11
。当我将代码段移植到c ++ 11
时,我发现了一个奇怪的事情。
代码spippet 使用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();
}
}
code snippet 下面没有编译:
#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();
}
}
这是Cruffier抱怨的内容:
<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;
| ^~~~
在我对第二个代码smippet进行了一些修改之后, a href =“ https://godbolt.org/z/epbn1otzz” rel =“ nofollow noreferrer”>此操作:
#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&lt&gt; view&gt;(view&gt;(即使
也有效,即使只有远期分界表view> view
在database
的定义之前,sharon_from_this())std ::::: unique_ptr&lt; view&gt;(新视图(shared_from_this())
在相同的条件下?
std::make_unique<T>
needs C++ 17
feature.It's a pity that I have to use C++11
. When I am porting the code snippet to C++11
, I found a strange thing.
The code snippet which uses make_unique
works well:
#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();
}
}
whereas the code snippet below does not compile:
#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();
}
}
Here is what the complier complains:
<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;
| ^~~~
After I did some modification for the second code snippet,this one works:
#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();
}
}
Why std::make_unique<View>(shared_from_this())
works even if there is only a forward delaration for View
before Database
's definition, whereas the compiler complains about std::unique_ptr<View>(new View(shared_from_this())
under the same condition?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
考虑此简化示例:
在
make_foo_1
,<代码中> std :: simolor_ptr&lt; foo&gt; 被制成依赖类型依赖类型 Make_unique&lt; foo&gt; ,这意味着它将绑定到unique> unique_ptr&lt; foo&gt;
。>在
中, >在模板点定义“ (即,
std :: simelod_ptr&lt; foo&gt;
)的定义,这意味着,在make_foo_2
中,编译器必须已经看到foo
的定义,否则它将抱怨foo
是不完整的类型。Consider this simplified example:
In
make_foo_1
,std::unique_ptr<foo>
is made a dependent type inmake_unique<foo>
which means that it'll postpone binding tounique_ptr<foo>
.But "Non-dependent names are looked up and bound at the point of template definition" (i.e., the definition of
std::unique_ptr<foo>
) which means that, inmake_foo_2
, the definition offoo
must have already been seen by the compiler or else it'll complain aboutfoo
being an incomplete type.当您拥有
std :: make_unique&lt; view&gt;(shared_from_this())
时,编译器需要实例化功能模板的专业化template
template&lt;类T,类,class ... args ... args&gt; std :: simel_ptr&lt; t&gt; std :: make_unique(args&amp;&amp; ...);
带有t = view,args = {&lt; empty&gt;}
。这发生在专业化的“实例化”。在某个地方使用它(当您调用make_unique
时,也是一个在翻译单元末尾的地方。您的编译器恰好在TU的末端实例化(如大多数编译器所做的那样),因此它恰好是“工作”,但实际上是不正确的(因为编译器在使用时可以实例化,并且会失败)。原因
std :: unique_ptr&lt; view&gt;(new View(shared_from_this()))
不起作用,是因为错误与expressionnew View(shared_from_this())
。没有模板功能或实例化点可以处理,因此编译器必须立即抱怨View
是不完整的,正如预期的那样。解决方案是延迟函数的定义,直到
view
完成:When you have
std::make_unique<View>(shared_from_this())
, the compiler needs to instantiate the specialization of the function templatetemplate<class T, class... Args> std::unique_ptr<T> std::make_unique(Args&&...);
withT = View, Args = {<empty>}
. This happens at a "point of instantiation" of the specialization. There is one where it is used (right when you callmake_unique
), and also one at the end of the translation unit. Your compiler happens to instantiate it at the the end of the TU (as most compilers do), so it happens to "work", but it's actually ill-formed (since the compiler could have instantiated when it was used and it would have failed).The reason
std::unique_ptr<View>(new View(shared_from_this()))
doesn't work is because the error is with the expressionnew View(shared_from_this())
. There is no template function or point of instantiation to deal with, so the compiler has to complain immediately thatView
is incomplete, as expected.The solution is to delay the definition of the function until
View
is complete: