1

我一直在设计类,它们都遵循这样的习惯用法,即它们的共享指针类型在它们的命名空间中可用,使用如下代码:

class ClassName
  {
  public:
    typedef std::shared_ptr<ClassName> ptr;
  }

可以编写如下代码:

ClassName::ptr p=std::make_shared<ClassName>();

现在,我想将该代码分解为一个基类。它可以让我神奇地在一个地方添加weak_ptr 支持,并指出哪些类符合该协议,并且通常更容易构建这些功能。

我是否被迫使用模板?

一种方法是遵循 enable_shared_from_this<> 方法。

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
  ...

似乎编译器必须在编译时知道该信息作为一种隐含的模板参数......这具有确保引用的类型是派生类而不是基类的额外好处。

有没有一种语法可以使这成为可能?

4

2 回答 2

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>;

但我想无论出于何种原因,您都希望能够将对象标记为“由智能指针管理”。

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>;

但我认为样板文件效果更好——SFINAEusing似乎有点矫枉过正。

于 2013-07-19T01:36:35.873 回答
1

所使用的方法enable_shared_from_this称为 CRTP,即“奇怪地重复出现的模板模式”。您需要指定派生类;基类模板无法询问谁将其用作基类。

但是您可以从enable_shared_from_this您的 CRTP 基中继承并避免指定派生类名称两次

于 2013-07-18T23:57:15.167 回答