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