c++visual-studiotemplate-specializationnatvis

C++ Partial Template Specialization and Natvis


I'm trying to create Visual Studio debug visualizers for a partially specialized type. For example, let's say I have something like this:

template <typename T>
struct Foo
{
    T bar;
};

template <typename T>
struct Foo<T*>
{
    T baz;
};

Without the partial specialization, this would be easy:

<Type Name="Foo&lt;*&gt;"> ... </Type>

With full specialization, it'd also be easy:

<Type Name="Foo&lt;int&gt;"> ... </Type>

But how do I cover the partial specialization? Is this even supported? If not, is there a workaround?


Solution

  • Short answer - No. You can't specify type qualifiers, references, and so on in natvis type name <Type Name="Foo&lt;*&gt;">.

    But:

    You can use the template's typename parameter as a string and compare with a type. For example, in the node's Condition attribute:

    <Type Name="Foo&lt;*&gt;">
      <DisplayString Condition="strcmp(&quot;$T1&quot;,&quot;short&quot;)==0">specialization short</DisplayString>
      <DisplayString Condition="strcmp(&quot;$T1&quot;,&quot;int &amp;&quot;)==0">specialization int &amp;</DisplayString>
      <DisplayString>unspecified specialization</DisplayString>
    </Type>
    

    For Foo<short> you will see specialization short and unspecified specialization for other.

    Example:

    template <typename T, typename U>
    struct Foo
    {
        T bar;
    };
    
    template <typename U>
    struct Foo<int &, U>
    {
        U baz;
    };
    int main()
    {
        int gg = 0;
        Foo<short, int> a;
        Foo<int, int> b;
        Foo<int &, int> c;
    

    Natvis:

    <Type Name="Foo&lt;*,*&gt;" >
      <DisplayString Condition="strcmp(&quot;$T1&quot;,&quot;short&quot;)==0">specialization short</DisplayString>
      <DisplayString>unspecified specialization</DisplayString>
    </Type>
    
    <Type Name="Foo&lt;int&amp;,*&gt;">
      <DisplayString>partial specialization int&amp;</DisplayString>
    </Type>
    

    Result:

    strcmp

    Or you, if you have some unique member in your partially specialized type, can use Priority option.

    Example:

    template <typename T>
    struct Foo
    {
        T bar;
    };
    
    template <typename U>
    struct Foo<U &>
    {
        U baz;
    };
    int main()
    {
        int g = 0;
        Foo<short> a;
        Foo<int> b;
        Foo<int &> c{g};
    

    Natvis:

    <Type Name="Foo&lt;*&gt;">
      <DisplayString>partial specialization {baz}</DisplayString>
    </Type>
    
    <Type Name="Foo&lt;*&gt;" Priority="Low">
      <DisplayString>other specialization</DisplayString>
    </Type>
    

    Result:

    Priority