Yochai Timmer
Yochai Timmer

Reputation: 49231

Can I add a breakpoint only for a specific template instantiation?

Let's say I have a templated class:

template <typename T>
class A
{
public:
   void foo() 
   {
      int i = 0; //breakpoint here only for type A<int>
   }
}

Can i somehow add a breakpoint, in Visual studio, that will only break inside foo for a certain instantiation ?

Like only for A<int>::foo ?

Let's assume I have 100's of templated A instantiations with different types.

Edit:

I do know how to make instantiations in a way that i could specialize a certain type.
The question is can i do it without specialization?

Upvotes: 20

Views: 4679

Answers (3)

Yochai Timmer
Yochai Timmer

Reputation: 49231

I found it.
Just put a breakpoint in the line you want (I'll show an example with std::shared_ptr<>).
Then go to the Breakpoints window and notice that when it breaks, there's a little + next to the breakpoint that will open all the different instantiations.
The line in bold is the breakpoint that is currently active.

Breakpoint on a templated function

Now, unfortunately, the Breakpoints window doesn't show you the actual template instantiation.
But, you can use the call stack to see which instantiation is currently used. Or, you can right click on each of the breakpoints, and choose "Go To Disassembly".

This may give you a hint as to the actual template instantiation. Then you can choose which breakpoints and for which type you want to keep active.

Disassembly

Edit: You could also add the Function column to the Breakpoints window and see the actual template function.

enter image description here

Upvotes: 31

user743382
user743382

Reputation:

You can add some code that will only be executed if T is an int, and set a breakpoint there. You could use std::is_same for that, or if you don't have the required header included and don't wish to add that, you can write a trivial function of your own:

template <typename T>
bool isint() { return false; }

template <>
bool isint<int>() { return true; }

template <typename T>
void f() {
    if (isint<T>())
        isint<T>();
    //  ^^^^^^^^^^^ set a breakpoint on that line

    // rest of your function
}

int main()
{
    f<char>();
    f<short>();
    f<int>();
    f<long>();
}

Testing shows that the breakpoint is hit only after f<char> and f<short> have already been called.

Upvotes: 5

Manu343726
Manu343726

Reputation: 14174

Since it's for debugging purposes, write a specialization covering that instantiation explicitly, putting the breakpoint there:

template <>
class A<int>
{
public:
   void foo() 
   {
      int i = 0; //breakpoint here 
   }
};

EDIT: Nested template + specialization

Since rewriting your class is not feasible, let's implement the function to be debugged inside a nested template, and specialize it:

template<typename T>
class A
{
public:
    void foo()
    {
        foo_impl<T,void>::exec();
    }

private:
    template<typename T, typename DUMMY>
    struct foo_impl
    {
        static void exec()
        {
            //Default impl
        }
    };

    template<typename DUMMY>
    struct foo_impl<int,DUMMY>
    {
        static void exec()
        {
            int i = 0; //Breakpoint here
        }
    }
};

Upvotes: 4

Related Questions