This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Multiple Abstract (contd)


I don't know what the standard mandates in terms of class layout in multiple inheritance, so I can't comment on that. Nevertheless, you can get rid the offset addition by introducing a class derived from base_1 and base_2, and deriving C from that composite class. The composite has to be known, and C can still be declared using the type_list templates. This way, you can at least know the base of C while *typing* the code.

Jacob Smith wrote:
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.






Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]