Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中获取编译时派生类的类型+;_C++_Templates_Types - Fatal编程技术网

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

C++ 在C+中获取编译时派生类的类型+;,c++,templates,types,C++,Templates,Types,我一直在设计类,这些类都遵循这样一个习惯用法,即它们的共享指针类型在名称空间中可用,代码如下: class ClassName { public: typedef std::shared_ptr<ClassName> ptr; } ClassName::ptr p=std::make_shared<ClassName>(); class ClassName:public SmartPointer<ClassName> ... 类

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

class ClassName
  {
  public:
    typedef std::shared_ptr<ClassName> ptr;
  }
ClassName::ptr p=std::make_shared<ClassName>();
class ClassName:public SmartPointer<ClassName>
   ...
类名
{
公众:
typedef std::共享\u ptr ptr;
}
使编写如下代码成为可能:

class ClassName
  {
  public:
    typedef std::shared_ptr<ClassName> ptr;
  }
ClassName::ptr p=std::make_shared<ClassName>();
class ClassName:public SmartPointer<ClassName>
   ...
ClassName::ptr p=std::make_shared();
现在,我想把代码分解成一个基类。它将让我神奇地在一个地方添加弱ptr支持,并将指示哪些类符合此协议,并且通常使构建功能更容易

我是被迫使用模板的吗

一种方法是遵循此方法中的enable_shared_

template <typename T>
class SmartPointer
  {
  public:
    typedef std::shared_ptr<T> ptr;
    typedef std::weak_ptr<T>   wptr;
  }
模板
类智能指针
{
公众:
typedef std::共享\u ptr ptr;
类型定义标准::弱ptr wptr;
}
允许我这样定义类:

class ClassName
  {
  public:
    typedef std::shared_ptr<ClassName> ptr;
  }
ClassName::ptr p=std::make_shared<ClassName>();
class ClassName:public SmartPointer<ClassName>
   ...
类类名:公共智能指针
...
但我觉得必须将ClassName指定为模板参数非常笨拙。我想做的是能够在编译时识别派生类的类型,替换下面的derivedClassType():

类智能指针
{
公众:
typedef std:shared_ptr ptr;
类型定义标准:弱ptr wptr;
}
类名:公共智能指针
...
似乎编译器必须知道编译时的信息是一种隐含的模板参数。。。这样做的另一个好处是确保引用的类型是派生类而不是基类


有一种语法可以实现这一点吗?

这个
enable\u shared\u使用的方法称为CRTP,即“奇怪的重复模板模式”。您需要指定派生类;基类模板无法询问谁在使用它作为基类


但是您可以在CRTP库中从
继承启用\u shared\u from\u this
,并避免两次指定派生类名。

因此,我将通过更改语法来作弊

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
完全清空:

struct Pointerable {};
并添加一个traits类:

template<typename T>
struct is_pointerable : std::is_base_of<Pointerable, T> {};
模板
struct是_pointerable:std::是{}的_base_;
然后我们使用:

template<typename T, typename=typename std::enable_if< is_pointerable<T>::value >::type >
using Ptr = std::shared_ptr<T>;
模板::类型>
使用Ptr=std::shared\u Ptr;

但我认为样板工作得更好——SFINAE
使用
似乎有些过火。

为什么<代码>自动p=std::使_共享()
更简单,并且不需要任何您正在执行的操作。而且,有趣的是,编译器在编译时不知道这些信息,因为
SmartPointer
没有基类。它是基类。C++11?另一方面,您要求编译器自动crtp。这是不存在的。@MooingDuck除了琐碎的事情之外,我对汽车没有什么特别的兴趣。也许随着时间的推移,我会改变主意,但我让编译器在Haskell中检测类型的经验表明,经过几层自动键入之后,事情开始变得不稳定。我发现更重要的是要明确,并尽早得到错误警告。@Yakk,C++11会很好,尽管它似乎没有帮助…模板别名不能重载,我认为SFINAE不适用于它们。感谢您的详细回复。我仍然在解压它,并注意到语法上的细微差别(例如使用VSTypeDef)。我认为您的替代语法是可以的,它只是用Ptr交换Class::Ptr,我认为这是可以的。我还认为,如果我采用模板化的Pointerable,我将能够在必要时创建一个围绕boost::intrusive_ptr的替代版本,并使用相同的ptr语法。是的,使用
Pointerable
的原因是要有一个
共享Pointerable
IntrusivePointerable
,使用一个接受类型并生成智能指针的工厂。为了连续性,我要提到的是,我遇到了@Yakk提出的解决方案的一些循环引用,这让我问了一个问题:这导致了与您建议的语法类似的语法,但是没有从trait类继承。@GB我的基类有一个
模板
别名而不是类型别名,这是有原因的<代码>使用ptr=std::shared\u ptr
与使用ptr=std::shared\u ptr的
模板非常不同——一个是循环依赖项,另一个不是。:)