Since I work with the ptr_container classes (especially ptr_vector and
ptr_map) quite a bit (very nice library!), I found it a little frustrating
attempting to debug container and iterator variables for these classes as
compared with how well the std containers show up in the VC++ watch window.
After some thought and experimentation I figured out how to add these
classes to the VC++ visualizer so that now these objects will display almost
as well as the std containers.
For those of you unfamiliar with the built-in visualizer (no surprise as
there is no official documentation for it), there is a text file called
autoexp.dat that contains definitions on how to display custom objects in
the watch window (including CString, std::string, and the standard
containers). I found this very helpful blog article that explains this in
more detail: http://www.virtualdub.org/blog/pivot/entry.php?id=120. The
autoexp.dat file is usually located in C:\Program Files\Microsoft Visual
Studio 8\Common7\Packages\Debugger.
Place the visualizer code (included down below) at the end of the
"visualizer" section of autoexp.dat (probably near the end of the file).
Some notes:
1. ptr_vector expands outs the same way as std::vector would rather than
std::vector<T>. I did it this way so you can easily see the memory address
of each contained object.
2. ptr_map unfortunately doesn't expand out exactly the same as
std::map. This is because ptr_map uses std::map internally
and not map. I couldn't figure out any way to auto convert the
sub-level appropriately. As a result the expanded entries only show the
value objects and not KEY and VALUE (e.g. where VALUE is the "second"
member). As a compromise I display the KEY elements in the preview section
so that you can still see them. The preview section can be seen in two
places: as a tooltip when you highlight the variable and on the first line
next to the variable in the watch window. If anyone can think of a
workaround or a better alternative let me know.
3. Also included is an entry for boost::array, so that these can be seen in
the watch window in the same manner as a static array.
Any questions?
Enjoy,
-- Bill --
Add the following text to autoexp.dat:
;---------------------------------------------------------------------------
---
; boost::ptr_vector
;---------------------------------------------------------------------------
---
boost::ptr_vector<*,*>{
children
(
#array
(
expr: (($T1**)($c.c_._Myfirst))[$i],
size : $c.c_._Mylast-$c.c_._Myfirst
)
)
preview
(
#(
"[",
$e.c_._Mylast - $e.c_._Myfirst ,
"](",
#array
(
expr : (($T1**)($c.c_._Myfirst))[$i],
size : $c.c_._Mylast-$c.c_._Myfirst
),
")"
)
)
}
;---------------------------------------------------------------------------
; boost::ptr_vector::iterator
;---------------------------------------------------------------------------
boost::void_ptr_iterator,*>{
preview
(
#(
($T2*)(*$c.iter_._Myptr)
)
)
children
(
#(
ptr: ($T2*)(*$c.iter_._Myptr)
)
)
}
;---------------------------------------------------------------------------
; boost::ptr_set::iterator
;---------------------------------------------------------------------------
boost::void_ptr_iterator<*,*>{
preview
(
#( ($T2*) $e.iter_._Ptr->_Myval)
)
children
(
#(ptr: ($T2*) $e.iter_._Ptr->_Myval)
)
}
;---------------------------------------------------------------------------
; boost::ptr_map
;---------------------------------------------------------------------------
boost::ptr_map<*,*,*>{
preview
(
#(
"[",
$e.c_._Mysize,
"](",
#tree
(
head : $c.c_._Myhead->_Parent,
skip : $c.c_._Myhead,
size : $c.c_._Mysize,
left : _Left,
right : _Right
) : $e._Myval.first,
")"
)
)
children
(
#tree
(
head : $c.c_._Myhead->_Parent,
skip : $c.c_._Myhead,
size : $c.c_._Mysize,
left : _Left,
right : _Right
) : ($T2*)$e._Myval.second
)
}
;---------------------------------------------------------------------------
; boost::ptr_map
;---------------------------------------------------------------------------
boost::ptr_multimap<*,*,*>{
preview
(
#(
"[",
$e.c_._Mysize,
"](",
#tree
(
head : $c.c_._Myhead->_Parent,
skip : $c.c_._Myhead,
size : $c.c_._Mysize,
left : _Left,
right : _Right
) : $e._Myval.first,
")"
)
)
children
(
#tree
(
head : $c.c_._Myhead->_Parent,
skip : $c.c_._Myhead,
size : $c.c_._Mysize,
left : _Left,
right : _Right
) : ($T2*)$e._Myval.second
)
}
boost::ptr_map_iterator<*,*,*>{
preview
(
#( "(", $c.iter_._Ptr->_Myval.first, ",", ($T3*)
$c.iter_._Ptr->_Myval.second, ")"
)
)
children
(
#(
key: $c.iter_._Ptr->_Myval.first,
value: ($T3*) $c.iter_._Ptr->_Myval.second,
_ptr: $c.iter_
)
)
}
;---------------------------------------------------------------------------
; boost::ptr_set
;---------------------------------------------------------------------------
boost::ptr_set<*,*>{
preview
(
#(
"[",
$e.c_._Mysize ,
"](",
#tree
(
head : $c.c_._Myhead->_Parent,
skip : $c.c_._Myhead,
left : _Left,
right : _Right,
size : $c.c_._Mysize
) : ($T1*)$e._Myval,
")"
)
)
children
(
#tree
(
head : $c.c_._Myhead->_Parent,
skip : $c.c_._Myhead,
left : _Left,
right : _Right,
size : $c.c_._Mysize
) : ($T1*)$e._Myval
)
}
;---------------------------------------------------------------------------
; boost::ptr_set
;---------------------------------------------------------------------------
boost::ptr_multiset<*,*>{
preview
(
#(
"[",
$e.c_._Mysize ,
"](",
#tree
(
head : $c.c_._Myhead->_Parent,
skip : $c.c_._Myhead,
left : _Left,
right : _Right,
size : $c.c_._Mysize
) : ($T1*)$e._Myval,
")"
)
)
children
(
#tree
(
head : $c.c_._Myhead->_Parent,
skip : $c.c_._Myhead,
left : _Left,
right : _Right,
size : $c.c_._Mysize
) : ($T1*)$e._Myval
)
}
;---------------------------------------------------------------------------
; boost::array
;---------------------------------------------------------------------------
boost::array<*,*>{
preview( $c.elems )
children
(
#array
(
expr: $c.elems[$i],
size : $T2
)
)
}