Re: c++ reflection (was (no subject))
OvermindDL1 <overminddl1 <at> gmail.com>
2010-07-01 21:50:46 GMT
On Tue, Jun 29, 2010 at 8:49 PM, Sylvain Vignaud <vignsyl <at> iit.edu> 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
Sweng-Gamedev <at> lists.midnightryder.com
http://lists.midnightryder.com/listinfo.cgi/sweng-gamedev-midnightryder.com