How to display underlying data in a type erasure class using shared_ptr

Viewed 204

Ok, so I've got a pretty straightforward class making use of type erasure, using a shared pointer.

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() {};
};

No issues here, however due to how it works, the debugger shows the complete chain from Prop, to the std::shared_ptr(PropContent), to PropModel, and finally the underlying templated prop, which contains the actual data.

What I'd like to do - is write a natvis rule to display that underlying data, instead of the entire chain. Unfortunately, the furthest I've gotten is to dereference the pointer, which just leaves me with the PropConcept struct that it points to.

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

So of course, my question is, how do I traverse the "tree" to get to the "prop" member of the PropModel struct? It doesn't matter if the class itself needs to be tweaked, or if it's just pure natvis - just as long as the type erasure remains, and I don't have to expand 4 items to get to the data.

Thanks in advance for any help.

2 Answers

It is as easy as adding logic for Prop::PropModel:

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

I have tested with

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

and the display is

enter image description here

As you can see your code for type Prop is not optimal. It could check for an empty shared_ptr and have an extra display for that. My logic for Prop::PropModel can also be improved if you want some type to be displayed differently, for example ints being displayed decimal.

By the way, you should enable MSVC code analysis. Your code triggers some warnings.

I eventually got a lot closer to Werner Henze's answer, but said answer supplied the final info I needed. For completion's sake, below is my final natvis for this class, as well as a picture of how it appears in the debugger. In this case, the shared_ptr points to a std::vector<int>

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

Which results in this...

Related