natvis中如何显示模板参数类型名称?

How to display template parameter type name in natvis?

我想为 (C++) 模板扩展一个 natvis 可视化工具 class。有没有办法显示第一个模板参数的类型名称?

如果 boost::variant<int,bool> v; v=1; 显示 1 (int) 或类似的东西就更好了

在我看来,最好的解决方案是使用标准的 C++17 std::variant。 MSVC 带有这种类型的 natvis,因此您可以清楚地了解存储的值。

这是我刚刚编写和测试的一些 natvis 代码:

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

它适用于任何 boost::variant<type_or_types>

它有一个 DisplayString 获取变体的成员 storage_ 并提取缓冲区 buf。然后将缓冲区的地址转换为指向提供给 std::variant 的类型的指针。正如您在我的代码中所见,which_ 是从零开始的,而模板参数是从 1 开始的。我对地址不感兴趣,只对值感兴趣,所以我在值前添加了一个*

我还添加了一个 Expand 部分,以便您可以扩展变体。这允许我显示 which_ 并再次显示值 - 这次 Type 列将显示正确的类型,如您在我的屏幕截图中所见(对于变体本身,类型显示为 boost::variant<…> 而且我不知道如何将类型名称添加到 DisplayString).

请注意 Optional="true" 是必需的,否则在传递的类型参数少于 7 个的情况下我们会得到解析错误(如 boost::variant<int,bool> 并且 natvis 没有 $T7.

如果您需要更多模板参数,您可以轻松扩展代码。

如果您希望 DisplayString 也显示索引(作为显式值或编码到名称 value… 中),您可以轻松地相应地更改它,如

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

最后但并非最不重要的一点请注意,我没有进行太多测试,也没有 boost::variant 深入研究。我看到 storage_ 有成员建议进行一些调整。所以仅仅使用 storage_.data_.buf 可能是不够的。可能需要根据使用的对齐方式调整指针。

如果要将 $T1 显示为字符串,请用 " 将其换行。例如,对于

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

在您的情况下,您会看到 1 "int"