На мой взгляд, лучшим решением является использование стандарта 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
. Возможно, потребуется настроить tуказатель в зависимости от используемого выравнивания.