很抱歉,这个问题很长,但有必要提供一些背景信息。我有一些代码似乎是我正在从事的项目的有用模式:

class Foo
{
public:
    Foo( int bar = 1 );
    ~Foo();
    typedef std::shared_ptr< Foo > pointer_type;
    static pointer_type make( int bar = 1 )
    {
        return std::make_shared< Foo >( bar );
    }

...
}

如您所见,它提供了一种将任何类构造为PointerType的直接方法,该类将shared_ptr封装为该类型:
auto oneFoo = Foo::make( 2 );

因此,您无需在整个代码库中放置对make_shared和shared_ptr的引用,即可获得shared_ptr的优点。

将智能指针类型封装在该类中具有以下优点:
  • 它使您可以控制指针类型的可复制性和可移动性。
  • 它对调用者隐藏shared_ptr详细信息,以便可以将非平凡的对象构造(例如引发异常的构造)放在Instance()调用中。
  • 当您使用使用多个智能指针实现的项目时,可以更改基础智能指针类型。您可以为特定类切换到unique_ptr甚至原始指针,并且调用代码将保持不变。
  • 将有关(智能)指针构造和别名的详细信息集中在最了解该操作的类中。
  • 它使您可以决定哪些类可以使用智能指针,以及哪些类必须在堆栈上构造。 PointerType字段的存在为调用者提供了有关可以创建与该类相对应的指针类型的提示。如果没有为一个类定义PointerType,则表明不能创建指向该类的指针。因此,必须在堆栈上以RAII样式创建特定的类。

  • 但是,我发现没有明显的方法可以在不直接键入必需的typedef和静态PointerType Instance()函数的情况下,将这段代码应用于项目中的所有类。我怀疑应该有一些一致的,C++ 11标准,跨平台的方法来使用基于策略的模板来执行此操作,但是经过一些试验并没有找到一种将其琐碎地应用于一堆类中的明显方法。可以在所有现代C++编译器上进行干净编译的方式。

    您能想到一种优雅的方法来将这些概念添加到一堆类中,而无需进行大量剪切和粘贴吗?理想的解决方案从概念上限制可以为哪种类型的类创建哪种类型的指针(一个类使用shared_ptr,另一个类使用原始指针),并且还可以通过其自己的首选方法处理任何受支持类型的实例化。通过在编译时适当地在非标准和标准智能指针和哑指针类型之间失败,这样的解决方案甚至可以处理和/或限制强制。

    最佳答案

    一种方法是使用curiously recurring template pattern

    template<typename T>
    struct shared_factory
    {
        using pointer_type = std::shared_ptr<T>;
    
        template<typename... Args>
        static pointer_type make(Args&&... args)
        {
            return std::make_shared<T>(std::forward<Args>(args)...);
        }
    };
    
    struct foo : public shared_factory<foo>
    {
        foo(char const*, int) {}
    };
    

    我相信这会给您您想要的。
    foo::pointer_type f = foo::make("hello, world", 42);
    

    然而...

    我不建议使用这种方法。试图指示类型的用户如何实例化该类型是不必要的限制。如果他们需要std::shared_ptr,则可以创建一个。如果他们需要std::unique_ptr,则可以创建一个。如果他们想在堆栈上创建一个对象,则可以。我认为,强制创建和管理用户对象的方法无济于事。

    要解决您的观点:



    这有什么好处?



    我不确定你在这里是什么意思。希望不是您可以捕获异常并返回nullptr。那将是Java级的。



    如果您正在使用多种智能指针,则最好让用户为给定情况选择适当的类型。此外,我认为具有相同的调用代码但返回不同类型的句柄可能会造成混淆。



    从什么意义上说,一个类对如何进行指针构造和别名了解“最多”?



    同样,我从根本上不同意必须以某种方式创建和管理某种类型的对象的想法。这就是singleton pattern如此阴险的原因之一。

    09-08 04:40