很抱歉,这个问题很长,但有必要提供一些背景信息。我有一些代码似乎是我正在从事的项目的有用模式:
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的优点。
将智能指针类型封装在该类中具有以下优点:
但是,我发现没有明显的方法可以在不直接键入必需的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如此阴险的原因之一。