$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
From: Filip KonviÄka (filip.konvicka_at_[hidden])
Date: 2007-05-30 11:17:11
> Doing the arithmetic blindly is impossible, since each index
> adds some overhead to the overall node structure. I don't think
> you can follow this approach.
>   
Yeah, I didn't mean it seriously, it was late night and I was bored from 
all those debugger complaints, so I just wanted to give it a try in that 
one specific case.
>>  From the "binary" point of view, is there some generic scheme that 
>> could be used to access the elements in the container? One can access 
>> node_count, but being able to display the list / array of elements would 
>> be nice (I don't think that it's necessary to be able to display the 
>> tree structure of ordered_unique, for instance), even if there are some 
>> additional requirements like that there is a sequenced<> index or that 
>> it is even the first of the indices.
>>     
> If you don't mind relying on index #0 being a sequenced one, then
> I think you can do it: the assumption about the first index being
> sequenced is equivalent to specifying that the type of the
> header node is of the form:
>
>   sequenced_index_node<Q>*
>
> where Q is some complex type involving the rest of indices as
> well as the value type (that I call T1 according to your
> convention when writing the visualizer). You already know how
> to traverse a sequenced index, but just to document it again,
> the expression to go from a node n (of a sequenced index) to the
> following is:
>
>  (sequenced_index_node<Q>*)
>    (sequenced_index_node_trampoline<Q>*)
>       ((sequenced_index_node_trampoline<Q>*)(n)->next_)
>   
This is OK, but first I need to get the node "n", which seems hard. This 
is because it is the "member" field of the container, which must be 
accessed via some down-cast to header_holder<T1, Tx>, and Tx depends on 
T2, but I can not derive Tx from T2 in the visualizer (I could use some 
typedefs from multi_index::detail to get Tx, but this is not supported 
by the debugger).
Specifically, given the multi_index_container<*,indexed_by<*>,*> > 
pattern, I need to cast the container variable to
   header_holder<sequenced_index_node<Q2> >, 
multi_index_container<T1,indexed_by<T2>,T3> >,
where Q2 is something like 
sequenced_index_node<hashed_index_node<index_node_base<T1> > >, which I 
don't know how to construct from T2.
[... long thinking ...]
So I tried to visualize sequenced_index_node instead of 
multi_index_container, and I have some progress.
I'm doing a cast to sequenced_index_node -> 
sequenced_index_node_trampoline --> sequenced_index_node_impl to get the 
head of the list, next items of the list are retrieved by applying 
".next_", and a node is displayed by casting sequenced_index_node_impl 
--> sequenced_index_node_trampoline --> sequenced_index_node. This is a 
next challenge point. The next cast would be 
*(int*)(boost::multi_index::detail::index_node_base<int>*), which would 
show the node data, but I don't know where to get the "int" type now :-)
[... long thinking ...]
I've come up with a solution that uses some compile-time support to 
derive a type that can be reached in the visualizer, which in essence 
enables to display the data. See the attached visualizer & sample code & 
screenshot.
Next, I will try to dispose of the neccessity of clicking through to the 
"member" field.
Thanks very much for support!
Cheers,
Filip
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
using namespace boost::multi_index;
using std::wstring;
template<typename T>
struct multi_index_helper {
};
#define VISUALIZE_MULTI_INDEX_CONTAINER(ID, Type)     \
typedef                                               \
  boost::multi_index::detail::multi_index_node_type<  \
    Type::value_type,                                 \
    Type::index_specifier_type_list,                  \
    std::allocator<Type::value_type> >::type          \
  VisHelper ## ID;                                    \
template<>                                            \
struct multi_index_helper<VisHelper ## ID> {          \
  Type::value_type value;                             \
}
struct test {
  wstring x;
  test(wchar_t const *str) : x(str) {}
  bool operator<(test const& other) const {
    return x<other.x;
  }
};
typedef multi_index_container<test, indexed_by<sequenced<>, ordered_unique<identity<test> > > > cont;
VISUALIZE_MULTI_INDEX_CONTAINER(testx, cont);
int main() {
  cont x;
  x.push_back(test(L"aaa"));
  x.push_back(test(L"bbb"));
  return 0; // see screenshot
}
boost::multi_index::detail::sequenced_index_node<*>{
 preview(#("multi_index container node"))
 children(
   #(
       #list (
               head : *(((boost::multi_index::detail::sequenced_index_node_impl*)(boost::multi_index::detail::sequenced_index_node_trampoline<$T1>*)&$c)->next_),
               size : 2,
               next : next_
       ) : *(multi_index_helper<boost::multi_index::detail::sequenced_index_node<$T1> >*)(boost::multi_index::detail::sequenced_index_node<$T1>*)(boost::multi_index::detail::sequenced_index_node_trampoline<$T1>*)(&$e),
     original members: [$c,!]
   )
 )
}
multi_index_helper<*> {
  preview(#($c.value))
}