【问题标题】:How to display template parameter type name in natvis?如何在 natvis 中显示模板参数类型名称?
【发布时间】:2019-06-24 19:28:22
【问题描述】:

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

boost::variant<int,bool> v; v=1; 显示 1 (int) 或类似的东西会很棒

【问题讨论】:

    标签: visual-c++ natvis


    【解决方案1】:

    在我看来,最好的解决方案是使用标准的 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&lt;type_or_types&gt;

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

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

    请注意,Optional="true" 是必需的,否则在传递的类型参数少于 7 个的情况下会出现解析错误(如 boost::variant&lt;int,bool&gt; 和 natvis 没有 $T7

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

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

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

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

    【讨论】:

    • 我实际上并没有要求可视化器进行变体。我要求将模板类参数显示为字符串的方式
    • @RomanKhvostikov 正如您在我的屏幕截图中看到的那样,Visual Studio 确实显示了类型(作为模板参数给出)。 vboost::variant&lt;int,bool&gt;,如果第一个类型正在使用,它会显示 value0 … &lt;the value&gt; … int。第三列中的int 正是作为模板参数提供的类型。如果要在第一列或者第二列添加类型,那么我必须说我怀疑这是否可以实现。
    【解决方案2】:

    如果要将$T1 显示为字符串,请使用" 将其包装起来。例如,对于

    &lt;DisplayString&gt;{*($T1*)storage_.data_.buf} {"$T1"}&lt;/DisplayString&gt;

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

    【讨论】:

    • 也可以取消引号,像这样:{"$T1",sb}。
    猜你喜欢
    • 1970-01-01
    • 2012-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    • 2019-09-30
    • 2011-04-03
    相关资源
    最近更新 更多