【发布时间】:2019-06-24 19:28:22
【问题描述】:
我想为 (C++) 模板类扩展 natvis 可视化器。有没有办法显示第一个模板参数的类型名称?
boost::variant<int,bool> v; v=1; 显示 1 (int) 或类似的东西会很棒
【问题讨论】:
标签: visual-c++ natvis
我想为 (C++) 模板类扩展 natvis 可视化器。有没有办法显示第一个模板参数的类型名称?
boost::variant<int,bool> v; v=1; 显示 1 (int) 或类似的东西会很棒
【问题讨论】:
标签: visual-c++ natvis
在我看来,最好的解决方案是使用标准的 C++17 std::variant。 MSVC 带有这种类型的 natvis,因此您可以清楚地了解存储的值。
这是我刚刚编写并测试过的一些 natvis 代码:
<Type Name="boost::variant<*>">
<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 可能还不够。根据所使用的对齐方式,可能需要调整指针。
【讨论】:
v 是 boost::variant<int,bool>,如果第一个类型正在使用,它会显示 value0 … <the value> … int。第三列中的int 正是作为模板参数提供的类型。如果要在第一列或者第二列添加类型,那么我必须说我怀疑这是否可以实现。
如果要将$T1 显示为字符串,请使用" 将其包装起来。例如,对于
<DisplayString>{*($T1*)storage_.data_.buf} {"$T1"}</DisplayString>
在你的情况下,你会看到1 "int"
【讨论】: