Finding member offset in compile time
Hi all, The question I have is not boost specific (maybe not even boost related), so if you think it is not appropriate to ask it here, please, please just tell me. So, here it goes. Is it possible to find the offset of a class member in compile time? In runtime, I can get the offset of member m1 in class A with the code offset = ((A *)0)->m1 But I want this value in compile time to use in some template metaprogramming. Is this possible? Since sizeof() is compile time, I suspect there is a way to do it. This would come very in hand for a metaprogramming based serialization library I am working on. Thanks in advance, Davi de Castro Reis If it is not appropriate to ask such questions here, could someone point me a C++ list where I could ask some advanced questions?
Davi de Castro Reis wrote:
So, here it goes. Is it possible to find the offset of a class member in compile time? In runtime, I can get the offset of member m1 in class A with the code
offset = ((A *)0)->m1
You can use the macro : offsetof(type, field) ... which returns qn int that you can use as an integer template argument ...
This would come very in hand for a metaprogramming based serialization library I am working on.
... but a much cleaner way is to use this C++ feature. This example prints 1234. #include <iostream> template< class T, class S, S (T::*P) > struct printer { void operator()( const T & aT ) const { std::cout << aT.*P ; }; }; struct X { int _i ; X() : _i(1234) {}; }; int main(void) { X aX ; printer< X, int, &X::_i>()( aX ); return 0 ; } This kind of library would be very useful for replacing some old and dirty code generators. Some years ago, I started to work on this kind of library, but missed some useful features like the ones Boost brought us. Let me please describe quickly what it could do, if it can help : * There was an object called a list of fields, defining, in a given order, a list of some or all data members, getters, or base classes, of a struct or class. * It was possible to plug one or several different list of fields, to an existing struct, without modification. * On top of that, you had operator, which took as parameters a list of fields, and an object of the struct associated to the list of fields. In your example, there was a serializing operator. To summarize, given a struct or class, you just needed one or several list of fields, to be able to serialize these fields only, in a specific order. There were operators for serializing to a screen, creating 'CREATE TABLE', 'INSERT' and 'SELECT' sql queries, writing to a network socket, filling Windows dialogs, etc... Feel free to take everything here (Sorry it is written in French) : http://remi.chateauneu.free.fr/CPlusPlus/reflection/reflection.htm
remi.chateauneu@gmx.de schrieb:
To summarize, given a struct or class, you just needed one or several list of fields, to be able to serialize these fields only, in a specific order.
There were operators for serializing to a screen, creating 'CREATE TABLE', 'INSERT' and 'SELECT' sql queries, writing to a network socket, filling Windows dialogs, etc...
I had a quick look at a code example of your library and like to add
that it is possible to do this without having to declare a list of
members outside the class:
struct Class{
FIELD(int,a);
};
#define FIELD(ValueT,name)
struct _##name##_Function{
inline void Register(){
_RegisterField
I had a quick look at a code example of your library and like to add that it is possible to do this without having to declare a list of members outside the class: -- Stefan Strasser
You're definitively right ! I made the design choice - which of course can be easily debated - to put the 'fields list' outside the class, for some reasons : - It may be useful, in some situations, to 'plug' reflection features on an existing class or struct, without changing it. - A specific application may need several different 'fields lists' on the same class or struct. I like your idea to encapsulate a data member which can, for example, provide clean accessors to these members. Is it possible to have the best of both worlds ? Given a plain, immutable 'Class' struct or class, the different 'fields lists' may be stored in derived classes containing several instantiations of a macro such as your 'FIELD', but which would not instantiate the member, but rather use the one of the base class. -- DSL Komplett von GMX +++ Superg�nstig und stressfrei einsteigen! AKTION "Kein Einrichtungspreis" nutzen: http://www.gmx.net/de/go/dsl
Chateauneu Remi schrieb:
You're definitively right ! I made the design choice - which of course can be easily debated - to put the 'fields list' outside the class, for some reasons : - It may be useful, in some situations, to 'plug' reflection features on an existing class or struct, without changing it.
- A specific application may need several different 'fields lists' on the same class or struct.
I agree that this is needed("fields I want to serialize", "fields I want
the user to see", etc.) but I don't think this should be part of a
reflection library.
one can still use a std::map
I like your idea to encapsulate a data member which can, for example, provide clean accessors to these members.
I'm not sure what you mean here. the _ClassField in the example behaves like the underlying type. if it's a class type it is derived from it, otherwise it has conversion ops. it has no accessors. -- Stefan Strasser
Uh, thanks for the help, Remi and Stefan.
I could actually implement what I wanted using your tips. So, in my
library, I can serialize any class given a "description" of it.
Something like this:
class A
{
int m1;
char *m2;
}
typedef make_traits
//A is now serializable. The CString class
//is a modifier to treat the second field
//as a c string
A x
A y
stream << pack(x)
stream >> unpack(y)
//Now x is equal to y
class B
{
unsigned int m1;
A *m2;
}
typedef make_traits
//B is now serializable. The NewPtr modifier
//says that the m2 should be treated as a C++ class
//pointer
This is rather cool and impressive. Using your tips I could go further,
so it was not needed anymore to specify the members in the correct
order, nor all of them.
But in the end I found it quite ugly. So I decided to go through a
another way, easier for the user and with a cleaner syntax, but not so
"hardcore". But your ideas are great, and probably have a good use. So,
thanks for the help.
[]s
Davi de Castro Reis
participants (4)
-
Chateauneu Remi
-
Davi de Castro Reis
-
remi.chateauneu@gmx.de
-
Stefan Strasser