Multiple Abstract (contd)

Jacob Smith jnsmith@utmb.edu
Thu Sep 11 02:21:00 GMT 2003


BTW, I'm trying not to stray too deeply into "how to program C++": I'm 
wondering about implementation specifics of GCC 3.X vs. the standard.

I found the notes about virtual functions and vtables at 2.5.5, a little 
more in 15.2/X in the standard. My question is if my solution to the 
problem (I include my the code at the end) only works for GCC 3.3.1 (and 
similar) or if there is further standardization of the vtable layout 
which isn't in the Stroustrup reference or, even better, I'm missing 
something obvious like static_cast<> etc. Basically, the layout I'm 
seeing is this:
class A /* virtual abstract base class*/
class B /* virtual abstract base class*/
class C : public A, public B /* concrete class, known only during 
compilation, not "before" or "after" - no typedefs etc. possible */
Layout of C
[pointer to vtable:A, sizeof(void*)][pointer to vtable:B, 
sizeof(void*)][data... sizeof(...)]
Using offsets into the layout of a class is an ugly hack and I was 
hoping for a more C++ish solution. Note that I can't get around the 
hashing of the pointer (the actual call is for the WNDCLASS{EX} in Win32 
using the cbWndExtra set to a pointer and a push of SetWindowLong and a 
pop of GetWindowLong). If the answer is "that's what you get for mixing 
old-school C with C++", that's fine. Also, note that the class type for 
the equivalent of class C is generated at compile-time, after I'm done 
"programming" - the type is unkown when I'm physically *typing* the code.
-j.

Burak Serdar wrote:

> If GetHashedValue() is a function that allocates an instance of class 
> concrete, and returns a char * (+4?), this is the correct behavior, as 
> the type cast is not safe. The +4 offset accounts for the vtable 
> pointer  of 'base_1', aligning a 'concrete' pointer to be a 'base_2'.


/* this function correctly creates an interface, given the concrete 
class C, and the type-list of inherit types */
template < typename T, typename type_list_T >
T& interface ( void *ptr ) {
   return *((T*)(ptr) + type_search<T,type_list_T>::result);
};
/* this is the declaration of type_search, going beyond the bounds 
returns N for an array of size N, or "one beyond the end" value */
template < typename search_T, typename type_list_T >
struct type_search;    // root inherit type
template < typename search_T >
struct type_search< search_T, type_terminator > {                    // 
result is based at 0
   enum { result = 0 };
};
template < typename search_T, typename U >
struct type_search< search_T, type_list<search_T,U> > {            // 
found what we're looking for
   enum { result = 0 };                                                
   // result is based at 0
};
template < typename search_T, typename T, typename U >
struct type_search< search_T, type_list<T,U> > {                    // 
searching at case N
   enum { result = 1 + type_search<search_T,U>::result };            
       // add 1, look in tail
};

/* defines a type-list */
template < typename T, typename U >
struct type_list {
   T head;
   U tail;
   typedef T head_T;
   typedef U tail_T;
   typedef type_list<T,U> type_list_T;
};
/* also code to generate a class which inherits every type of a 
type-list, sort, append, erase etc. etc. */

The type-lists are derived from the algorithms/data structures in 
"Modern C++ Design", Andrei Alexandrescu, 2001, Addison-Wesley etc. etc.





More information about the Gcc-help mailing list