我一直在设计类,这些类都遵循这样的习惯用法:它们的共享指针类型在其命名空间中可用,使用如下代码:
class ClassName
{
public:
typedef std::shared_ptr<ClassName> ptr;
}
可以编写如下代码:
ClassName::ptr p=std::make_shared<ClassName>();
现在,我想将该代码纳入基类。它会让我在一个地方神奇地添加weak_ptr支持,并指出哪些类符合这个协议,并且通常可以更容易地构建这些功能。
我被迫使用模板吗?
一种方法是关注enable_shared_from_this&lt;&gt;方法
template <typename T>
class SmartPointer
{
public:
typedef std::shared_ptr<T> ptr;
typedef std::weak_ptr<T> wptr;
}
允许我定义这样的类:
class ClassName:public SmartPointer<ClassName>
...
但是我不得不指定ClassName作为模板参数,这让我感到笨拙。我想要做的是能够在编译时识别派生类的类型,替换下面的derivedClassType():
class SmartPointer
{
public:
typedef std:shared_ptr<derivedClassType()> ptr;
typedef std:weak_ptr<derivedClassType()> wptr;
}
class ClassName: public SmartPointer
...
似乎编译器必须在编译时将该信息知道为一种隐含的模板参数...这样做的另一个好处是确保引用的类型是派生类而不是基类。
是否有可以实现此目的的语法?
答案 0 :(得分:1)
enable_shared_from_this
使用的方法称为CRTP,即“奇怪的重复模板模式”。您需要指定派生类;基类模板无法询问谁将其用作基类。
但您可以从CRTP基础中的enable_shared_from_this
继承,并避免指定派生类名两次。
答案 1 :(得分:1)
所以,我会通过改变你的语法来作弊。
template<typename T>
using Ptr = T::template ptr<T>;
template<typename T>
using WPtr = T::template wptr<T>;
struct Pointerable {
template<typename T>
using ptr = std::shared_ptr<T>;
template<typename T>
using wptr = std::weak_ptr<T>;
};
class Foo : public Pointerable {
};
Ptr<Foo> x = std::make_shared<Foo>( ... );
WPtr<Foo> y = x;
此处,Pointerable
的唯一目的是标记您要使用的类型。可以编写Ptr<Foo>
和WPtr<Foo>
来处理任何类:
template<typename T>
using Ptr = std::shared_ptr<T>;
template<typename T>
using WPtr = std::weak_ptr<T>;
但我想你希望能够将对象标记为&#34;由智能指针管理&#34;无论出于何种原因。
如果您不喜欢其中的Pointerable
样板,我们甚至可以让template
完全为空:
struct Pointerable {};
并添加一个特质类:
template<typename T>
struct is_pointerable : std::is_base_of<Pointerable, T> {};
然后我们使用:
template<typename T, typename=typename std::enable_if< is_pointerable<T>::value >::type >
using Ptr = std::shared_ptr<T>;
但我觉得样板效果更好 - SFINAE using
似乎有点矫枉过正。