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<*>">
<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"
我想为 (C++) 模板扩展一个 natvis 可视化工具 class。有没有办法显示第一个模板参数的类型名称?
如果 boost::variant<int,bool> v; v=1;
显示 1 (int)
或类似的东西就更好了
在我看来,最好的解决方案是使用标准的 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
可能是不够的。可能需要根据使用的对齐方式调整指针。
如果要将 $T1
显示为字符串,请用 "
将其换行。例如,对于
<DisplayString>{*($T1*)storage_.data_.buf} {"$T1"}</DisplayString>
在您的情况下,您会看到 1 "int"