提问者:小点点

如何使用shared_ptr在类型擦除类中显示基础数据


好的,所以我有一个非常简单的类,使用共享指针使用类型擦除。

class Prop
{
    struct PropConcept
    {
        virtual ~PropConcept() {}
    };
    template<typename T>
    struct PropModel : PropConcept
    {
        PropModel(const T& t) : prop(t) { }
        PropModel() {}
        virtual ~PropModel() {}
    private:
        T prop;
    };

    std::shared_ptr<PropConcept> prop;
public:

    template<typename T>
    Prop(const T& obj) : prop(new PropModel<T>(obj)) { }
    Prop() {};
};

这里没有问题,但是由于它的工作方式,调试器显示了从prop到std::shared_ptr(PropContent),再到PropModel,最后是包含实际数据的底层模板化Prop的完整链。

我想做的是编写一个 natvis 规则来显示底层数据,而不是整个链。不幸的是,我得到的最远的是取消引用指针,这只给我留下了它指向的 PropConcept 结构。

<Type Name="Prop">
   <DisplayString>{*prop}</DisplayString>
   <Expand>
      <Item Name="prop">(*prop)</Item>
   </Expand>
</Type>

所以当然,我的问题是,我如何遍历“树”以获得 PropModel 结构的“prop”成员?类本身是否需要调整,或者它是否只是纯粹的 natvis 并不重要 - 只要类型擦除仍然存在,我不必扩展 4 个项目来获取数据。

提前感谢任何帮助。


共2个答案

匿名用户

这就像为<code>Prop::PropModel</code>添加逻辑一样简单:

<Type Name="Prop::PropModel&lt;*&gt;">
  <DisplayString>{prop}</DisplayString>
  <Expand>
    <Item Name="prop">prop</Item>
  </Expand>
</Type>

我已经测试过了

Prop p1{};
Prop p2{ 42 };
Prop p3{ std::string{"x"} };

并且显示器是

正如你所看到的,类型Prop的代码不是最优的。它可以检查一个空的shared_ptr并有一个额外的显示。如果你想以不同的方式显示某些类型,我的Prop::PropModel的逻辑也可以得到改进,例如int的显示方式是十进制的。

顺便说一下,您应该启用MSVC代码分析。您的代码会触发一些警告。

匿名用户

我最终非常接近沃纳·亨策的答案,但他说答案提供了我需要的最终信息。为了完整起见,下面是我的这个类的最终natvis,以及它如何出现在调试器中的图片。在这种情况下,shared_ptr指向一个< code>std::vector

  <Type Name="Prop">
    <DisplayString>{*prop}</DisplayString>
    <Expand>
      <ExpandedItem>(*prop)</ExpandedItem>
    </Expand>
  </Type>

  <Type Name="Prop::PropModel&lt;*&gt;">
    <DisplayString>{prop}</DisplayString>
    <Expand>
      <ExpandedItem>prop</ExpandedItem>
    </Expand>
  </Type>