Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display template parameter type name in natvis?

I want to extend a natvis visualizer for a (C++) template class. Is there a way to display a type name of the first template parameter?

It would be great for boost::variant<int,bool> v; v=1; to display 1 (int) or something like that

like image 884
Roman Khvostikov Avatar asked Jan 31 '19 10:01

Roman Khvostikov


2 Answers

If you want to show $T1 as a string, wrap it with ". For example, for

<DisplayString>{*($T1*)storage_.data_.buf} {"$T1"}</DisplayString>

in your case you will see 1 "int"

like image 175
mr NAE Avatar answered Nov 15 '22 10:11

mr NAE


In my opinion the best solution is to use the standard C++17 std::variant. MSVC comes with natvis for this type so that you have a pretty view of the value that is stored.

Here is some natvis code that I just wrote and tested:

  <Type Name="boost::variant&lt;*&gt;">
    <DisplayString Condition="which_==0">{*($T1*)storage_.data_.buf}</DisplayString>
    <DisplayString Condition="which_==1" Optional="true">{*($T2*)storage_.data_.buf}</DisplayString>
    <DisplayString Condition="which_==2" Optional="true">{*($T3*)storage_.data_.buf}</DisplayString>
    <DisplayString Condition="which_==3" Optional="true">{*($T4*)storage_.data_.buf}</DisplayString>
    <DisplayString Condition="which_==4" Optional="true">{*($T5*)storage_.data_.buf}</DisplayString>
    <DisplayString Condition="which_==5" Optional="true">{*($T6*)storage_.data_.buf}</DisplayString>
    <DisplayString Condition="which_==6" Optional="true">{*($T7*)storage_.data_.buf}</DisplayString>
    <Expand>
      <Item Name="which">which_</Item>
      <Item Name="value0" Condition="which_==0">*($T1*)storage_.data_.buf</Item>
      <Item Name="value1" Condition="which_==1" Optional="true">*($T2*)storage_.data_.buf</Item>
      <Item Name="value2" Condition="which_==2" Optional="true">*($T3*)storage_.data_.buf</Item>
      <Item Name="value3" Condition="which_==3" Optional="true">*($T4*)storage_.data_.buf</Item>
      <Item Name="value4" Condition="which_==4" Optional="true">*($T5*)storage_.data_.buf</Item>
      <Item Name="value5" Condition="which_==5" Optional="true">*($T6*)storage_.data_.buf</Item>
      <Item Name="value6" Condition="which_==6" Optional="true">*($T7*)storage_.data_.buf</Item>
    </Expand>
  </Type>

It works for any boost::variant<type_or_types>.

It has a DisplayString that takes the variant's member storage_ and extracts the buffer buf. The address of the buffer is then cast to a pointer to the type that was provided to std::variant. As you can see in my code which_ is zero based, whereas the template parameters are 1 based. I am not interested in the address but in the value, so I am adding a * in front of the value.

I also added an Expand section so that you can expand a variant. This allows me to show which_ and to show the value again - this time the column Type will show the correct type as you can see in my screen capture (for the variant itself the type is displayed as boost::variant<…> and I do not know how to add the type name into the DisplayString).

Please note that the Optional="true" are required because otherwise we would get a parsing error in cases where less than 7 type parameters are passed (as in boost::variant<int,bool>and natvis does not have a $T7.

If you need more template parameters, you can easily extend the code.

If you want the DisplayString to also shows the index (as an explicit value or coded into the name value…), you can easily change it accordingly as in

<DisplayString Condition="which_==0">{{which={which_} value0={*($T1*)storage_.data_.buf}}}</DisplayString>

Last but not least please note that I did not test very much and that I did not look into boost::variant into detail. I saw that storage_ has members suggesting that there is some alignment in place. So it might not be sufficient to just use storage_.data_.buf. It might be necessary to adjust the pointer depending on the alignment being used.

View in Debugger

like image 42
Werner Henze Avatar answered Nov 15 '22 10:11

Werner Henze