“ std :: make_unique”和`sTD :: simel_ptr`与正向声明之间的奇怪行为

发布于 2025-02-06 17:06:06 字数 4089 浏览 3 评论 0原文

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> viewdatabase的定义之前,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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

滴情不沾 2025-02-13 17:06:06

为什么std :: make_unique&lt; view&gt;(shared_from_this())即使在view> view> view> database之前,即使只有远期分配也有效的定义,而编译器则抱怨std :: simolor_ptr&lt; view&gt;(新视图(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 {};

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是不完整的类型。

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?

Consider this simplified example:

#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> is made a dependent type in make_unique<foo> which means that it'll postpone binding to unique_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, in make_foo_2, the definition of foo must have already been seen by the compiler or else it'll complain about foo being an incomplete type.

雾里花 2025-02-13 17:06:06

当您拥有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()))不起作用,是因为错误与expression 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()));
}

When you have std::make_unique<View>(shared_from_this()), the compiler needs to instantiate the specialization of the function template template<class T, class... Args> std::unique_ptr<T> std::make_unique(Args&&...); with T = View, Args = {<empty>}. This happens at a "point of instantiation" of the specialization. There is one where it is used (right when you call make_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 expression new View(shared_from_this()). There is no template function or point of instantiation to deal with, so the compiler has to complain immediately that View is incomplete, as expected.

The solution is to delay the definition of the function until View is complete:

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()));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文