在C ++中编译时获取派生类的类型

时间:2013-07-18 23:44:42

标签: c++ templates types

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

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

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

是否有可以实现此目的的语法?

2 个答案:

答案 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似乎有点矫枉过正。