Re: c++ reflection (was (no subject))
OvermindDL1 <[email protected]> Thu, 1 Jul 2010 15:50:46 -0600
| Newsgroups | gmane.games.devel.sweng |
|---|---|
| Message-ID | <[email protected]> |
On Tue, Jun 29, 2010 at 8:49 PM, Sylvain Vignaud <[email protected]> wrote: > Not sure anyone is still following this thread. I've just spent 10mn to > improve the interface so that the Member macro doesn't have such a rigid > number of arguments: > > I think the following code is quite easily expandable, and it now looks > quite much like what Jarkko wanted: easy to have lots of parameters, no code > generation tool, no precompilation pass. > > class Foo > { > public: > Foo() {} > virtual ~Foo() {} > > private: > DefineClass(Foo); > > Member(int, test, Default(0); Description("Some int") ); > Member(char *, mName, Default("foo"); Description("Some static text"); > Serialized()); > > Member(int*, mBuffer, Default(NULL), Description("Some ptr to nowhere"); > Serialized()); > > Member(int, foo); > > Member(int, foo2, Description("this one has a desc, unlike foo")); > Member(int, foo3, Default(0xDead)); > > EndClass(); > }; > > Updated code is still in the same place: > http://tfpsly.free.fr/Files/Reflection.cpp > > > > On 24/06/10 00:24, Sylvain G. Vignaud wrote: > > Actually you can get something quite similar if you're not too regarding on > mixing metaprogramming and macros. The result looks like: > class Foo > { > public: > Foo() {} > virtual ~Foo() {} > private: > DefineClass(Foo); > > Member(int, test, 0); > Member(char *, mName, "foo"); > > Member(int*, mBuffer, NULL); > > EndClass(Foo); > }; > Foo foo; > foo.InitializeMembersToDefaultValue(); > const Foo::ClassDescription &desc = Foo::GetClassDescription(); > printf("type: %s\n", desc.name()); > printf("size: %d\n", desc.size()); > for( int i=0; i<Foo::NbrMembers; ++i ) > { > const member_t &member = desc.m_Members[i]; > printf(" %s: offset %d size %d type %s\n", > member.name, member.offset, > member.type->size(), member.type->name()); > } > And it seems the "Member" macro doesn't prevent Intellisense and the likes > to know about members :) > Also it could be expended to take more parameters, like a flag to decide > which members are serialized, a text description... > Quick proof of concept with full code - hacked using Jon Watte's > Reflexion.cpp as a basis: > http://tfpsly.free.fr/Files/Reflection.cpp > From: Jarkko Lempiainen [Profoundic] <jarkko > > [...] But it would be nicer to have something like: > struct my_struct > { > int a {serialized, editable, desc("Car velocity"), color(0x123456)}; > int b {serialized, editable, call(foobar())}; > int c, d, e {serialized}; > int f; // non-reflected variable > }; > Cheers, Jarkko > From: sweng-gamedev-bounces <at> lists.midnightryder.com > [mailto:sweng-gamedev-bounces <at> lists.midnightryder.com] On Behalf Of Jon > Watte > Sent: Thursday, June 17, 2010 1:13 AM > Am 17.06.2010 00:12, schrieb Jon Watte: > > Mail formatting still all messed up :-( > Anyway, the example you had (PFC_MONO()) doesn't actually add all the > annotations you want for editing and serialization in addition to the > general reflection information. > You can get rid of the ellipsis requirement by doing something like: > #define MEMBERS(Type, x) \ > typedef mytype Type; \ > inline static Member *GetMembers() { \ > static Member<mytype>[] members = { \ > x \ > }; \ > return x; \ > } > #define MEMBER(x, desc) Member<mytype>(&mytype::x, #x, desc), > Use it like so: > struct MyStruct { > int x; > float b; > MEMBERS(MyStruct, > MEMBER(x, "Some integer value") > MEMBER(b, "The amount of float-ness")) > }; > Note that the comma lives in the MEMBER() macro, and the members are > just listed without comma within the MEMBERS() macro. The MEMBER() > macro should take the union of all information you need about the > member (editor information, networking, etc). Still seems like it has a lot of oddity in its syntax, what about something like this, which is completely possible and rather easily done actually: class Foo { public: Foo() {} virtual ~Foo() {} private: DefineClass(Foo); // Why not make this define the actual class in its entirety? Member((type(int))(name(test))(default(0))(description("Some int")); Member((type(char*))(name(mName))(default("foo"))(description("Some static text"))(serialized)); Member((type(int*))(name(mBuffer))(default(NULL))(description("Some ptr to nowhere"))(serialized); Member((type(int))(name(foo))); Member((type(int))(name(foo2))(description("this one has a desc, unlike foo"))); Member((type(int))(name(foo3))(default(0xDead))); EndClass(); }; That style lets you add new capabilities arbitrarily without introducing new Member overloads or what-not, just adding a keyword, simple to do. Or if you want to use the Boost proposed Mirror C++ reflection library, it would be this (this is non-intrusive for note): class Foo { public: Foo() {} virtual ~Foo() {} int test; char *mName; int *mBuffer; int foo; int foo2; int get_foo3() const; void set_foo3(const int i); float someFunc(int); private: int foo3; }; BOOST_MIRROR_REG_BEGIN BOOST_MIRROR_REG_CLASS_GLOBAL_SCOPE_BEGIN(class, foo) BOOST_MIRROR_REG_CLASS_MEM_VARS_BEGIN BOOST_MIRROR_REG_CLASS_MEM_VAR(public, _, _, test) BOOST_MIRROR_REG_CLASS_MEM_VAR(public, _, _, mName) BOOST_MIRROR_REG_CLASS_MEM_VAR(public, _, _, mBuffer) BOOST_MIRROR_REG_CLASS_MEM_VAR(public, _, _, foo) BOOST_MIRROR_REG_CLASS_MEM_VAR(public, _, _, foo2) BOOST_MIRROR_REG_CLASS_MEM_VAR_GET_SET( private, _, int, foo3, _.get_foo3(), _.set_foo3(_a) ) BOOST_MIRROR_REG_CLASS_MEM_VARS_END float someFunc(int); BOOST_MIRROR_REG_MEM_FUNCTION_BEGIN(public, _, float, someFunc, someFuncI) BOOST_MIRROR_REG_MEM_FUNCTION_PARAM(int, i) BOOST_MIRROR_REG_MEM_FUNCTION_END(someFunc, someFuncI) BOOST_MIRROR_REG_CLASS_END And it has things to handle type conversions supported and much more. The docs are at: http://kifri.fri.uniza.sk/~chochlik/mirror-lib/html/ _______________________________________________ Sweng-Gamedev mailing list [email protected] http://lists.midnightryder.com/listinfo.cgi/sweng-gamedev-midnightryder.com