By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,865 Members | 1,453 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,865 IT Pros & Developers. It's quick & easy.

Compile-time introspection

P: n/a
Is there a way to generate a series of statements based on the data members of
a structure at compile time?

I have a function that reverses the endianness of any data structure:

/// Reverse the endianness of a data structure "in place".
template <typename T>
void reverseEndian(T&);

Using boost, it is possible to provide the default implementation for all POD
types (i.e. simply reverse the bytes in the data item's representation).

Until today, I have purposely not provided the implementation for structures,
forcing the user of the function to provide an implementation for each
structure, for example:

struct S
{
int a;
float b;
double c;
};

template <void reverseEndian(S& s)
{
// Function body -- can this be automated?
reverseEndian<>(s.a);
reverseEndian<>(s.b);
reverseEndian<>(s.c);
}

Is it possible to automatically generate the contents of the specialization?
This calls for introspection (the language feature, not the Zen philosophy),
and so far I have not found any way to do it, portable or otherwise.

-dr
Feb 18 '07 #1
Share this Question
Share on Google+
14 Replies


P: n/a
Dave Rahardja wrote:
Is there a way to generate a series of statements based on the data members of
a structure at compile time?

I have a function that reverses the endianness of any data structure:

/// Reverse the endianness of a data structure "in place".
template <typename T>
void reverseEndian(T&);

Using boost, it is possible to provide the default implementation for all POD
types (i.e. simply reverse the bytes in the data item's representation).

Until today, I have purposely not provided the implementation for structures,
forcing the user of the function to provide an implementation for each
structure, for example:

struct S
{
int a;
float b;
double c;
};

template <void reverseEndian(S& s)
{
// Function body -- can this be automated?
reverseEndian<>(s.a);
reverseEndian<>(s.b);
reverseEndian<>(s.c);
}

Is it possible to automatically generate the contents of the specialization?
This calls for introspection (the language feature, not the Zen philosophy),
and so far I have not found any way to do it, portable or otherwise.
I don't know of a means of doing this, when faced with this kind of a
problem, I tend to resort to code generation.

--
Ian Collins.
Feb 18 '07 #2

P: n/a
Dave Rahardja wrote:
Is there a way to generate a series of statements based on the data members of
a structure at compile time?

I have a function that reverses the endianness of any data structure:

/// Reverse the endianness of a data structure "in place".
template <typename T>
void reverseEndian(T&);

Using boost, it is possible to provide the default implementation for all POD
types (i.e. simply reverse the bytes in the data item's representation).

Until today, I have purposely not provided the implementation for structures,
forcing the user of the function to provide an implementation for each
structure, for example:

struct S
{
int a;
float b;
double c;
};

template <void reverseEndian(S& s)
{
// Function body -- can this be automated?
reverseEndian<>(s.a);
reverseEndian<>(s.b);
reverseEndian<>(s.c);
}

Is it possible to automatically generate the contents of the specialization?
This calls for introspection (the language feature, not the Zen philosophy),
and so far I have not found any way to do it, portable or otherwise.

-dr
There are a lot of ways to do introspection in C++. So far
the most portable one is to use macros. The idea is, as you
define classes you also put plain Macros that expand to code
that will help you do introspection. Here is a quick example:

class A
{
public:
// your regualr C++ goes here
void foo();
int bar;
public:
// introspection via macros
REFLECT_MEM_FUNC( foo, ...... );
REFLECT_MEM_VAR( bar, ... );
};

But I honestly hate this approach since when I go read a class,
it doubles up the length of the class just because of those
manual introspection lines. Plus it is prone to user error. Like
if you misspelled something or omitted something.

Wouldn't it be cool if you wrote regular C++ and somehow, someway
the C++ language created the necessary data by itself? This is
currently being discussed by the C++ LWG and proposals have been
made. Unfortunately, it will be a while until we get an answer about
this issue since it is still labeled "Open" status by the LWG.

And then there are some talented people who come to the rescue:

http://seal-reflex.web.cern.ch/seal-reflex/

Good Luck!
Feb 19 '07 #3

P: n/a

BTW, on second reading, you wanted to do Compile-time introspection:

I would look into heavy use of template metaprogramming to do this.
If that is too exotic for you, run-time introspection could be a good
alternative for you. (The stuff I originally posted.)

Good Luck!
Piyo wrote:
Dave Rahardja wrote:
>Is there a way to generate a series of statements based on the data
members of
a structure at compile time?

I have a function that reverses the endianness of any data structure:

/// Reverse the endianness of a data structure "in place".
template <typename T>
void reverseEndian(T&);

Using boost, it is possible to provide the default implementation for
all POD
types (i.e. simply reverse the bytes in the data item's representation).

Until today, I have purposely not provided the implementation for
structures,
forcing the user of the function to provide an implementation for each
structure, for example:

struct S
{
int a;
float b;
double c;
};

template <void reverseEndian(S& s)
{
// Function body -- can this be automated?
reverseEndian<>(s.a);
reverseEndian<>(s.b);
reverseEndian<>(s.c);
}

Is it possible to automatically generate the contents of the
specialization?
This calls for introspection (the language feature, not the Zen
philosophy),
and so far I have not found any way to do it, portable or otherwise.

-dr

There are a lot of ways to do introspection in C++. So far
the most portable one is to use macros. The idea is, as you
define classes you also put plain Macros that expand to code
that will help you do introspection. Here is a quick example:

class A
{
public:
// your regualr C++ goes here
void foo();
int bar;
public:
// introspection via macros
REFLECT_MEM_FUNC( foo, ...... );
REFLECT_MEM_VAR( bar, ... );
};

But I honestly hate this approach since when I go read a class,
it doubles up the length of the class just because of those
manual introspection lines. Plus it is prone to user error. Like
if you misspelled something or omitted something.

Wouldn't it be cool if you wrote regular C++ and somehow, someway
the C++ language created the necessary data by itself? This is
currently being discussed by the C++ LWG and proposals have been
made. Unfortunately, it will be a while until we get an answer about
this issue since it is still labeled "Open" status by the LWG.

And then there are some talented people who come to the rescue:

http://seal-reflex.web.cern.ch/seal-reflex/

Good Luck!

Feb 19 '07 #4

P: n/a
On Mon, 19 Feb 2007 01:24:18 GMT, Piyo <cy*********@yahoo.comwrote:
>
BTW, on second reading, you wanted to do Compile-time introspection:

I would look into heavy use of template metaprogramming to do this.
If that is too exotic for you, run-time introspection could be a good
alternative for you. (The stuff I originally posted.)

Good Luck!
(ignoring top-post faux pas)

I am conversant with template metaprogramming, but still find no way to do
compile-time introspection.

-dr
Feb 19 '07 #5

P: n/a
Piyo wrote:
>
There are a lot of ways to do introspection in C++. So far
the most portable one is to use macros. The idea is, as you
define classes you also put plain Macros that expand to code
that will help you do introspection. Here is a quick example:
I don't think so, not according to the traditional use of the term, to
be able to examine and possibly modify, an object at runtime. This
would permit a serialise function to determine the data members of a
class and automatically serialise them.

In C++, the only alternative is code generation or some form of
meta-compilation.

--
Ian Collins.
Feb 19 '07 #6

P: n/a
Ian Collins wrote:
Piyo wrote:
>There are a lot of ways to do introspection in C++. So far
the most portable one is to use macros. The idea is, as you
define classes you also put plain Macros that expand to code
that will help you do introspection. Here is a quick example:
I don't think so, not according to the traditional use of the term, to
be able to examine and possibly modify, an object at runtime. This
would permit a serialise function to determine the data members of a
class and automatically serialise them.
It depends on how you define introspection. Some only deal with the fact
that at run-time, you would like to be able to determine what are the
member functions and what are the member variables and or types and such
or even what are their superclasses too. From that point of view, if you
only plan on "querying introspection", then macros and Reflex can do
this for you. Please invest the time to go to the website and check it
out for yourself. Based on the macro or Reflex approach, you can write a
serialization function ONCE and then the magic of introspection will
work immediately. I serialize my "Reflexed" classes by first generating
a database schema on the fly and then serialize them to and from the
database. Go to the site and you might be amazed. I have it working in
practice.

If you plan on taking a class and possibly defining its make up at
runtime, you can still also do that (albeit very very ugly IMO) but it
requires a framework of classes and stuff to do so. I believe I did see
one out there. That will satisfy both sides of the equation of
introspection. But for my needs, I did not require a dynamic make up of
a class's structure so I went and used Seal Reflex.
>
In C++, the only alternative is code generation or some form of
meta-compilation.
And that's exactly what Seal does (and macros too since it creates code
for you in a sense). Also, if you check out the C++ LWG, a proposal has
been submitted to address this very issue of introspection in C++ and it
does have a very very good background survey of the state-of-the-art in
this. I just find it sad that the LWG has put it on the backburner.
Feb 19 '07 #7

P: n/a
* Dave Rahardja:
Is there a way to generate a series of statements based on the data members of
a structure at compile time?

I have a function that reverses the endianness of any data structure:

/// Reverse the endianness of a data structure "in place".
template <typename T>
void reverseEndian(T&);

Using boost, it is possible to provide the default implementation for all POD
types (i.e. simply reverse the bytes in the data item's representation).

Until today, I have purposely not provided the implementation for structures,
forcing the user of the function to provide an implementation for each
structure, for example:

struct S
{
int a;
float b;
double c;
};

template <void reverseEndian(S& s)
{
// Function body -- can this be automated?
reverseEndian<>(s.a);
reverseEndian<>(s.b);
reverseEndian<>(s.c);
}

Is it possible to automatically generate the contents of the specialization?
This calls for introspection (the language feature, not the Zen philosophy),
and so far I have not found any way to do it, portable or otherwise.
No, you can't do what you want directly, at least as of the current
standard.

But yes, there other ways.

One way is to note that if you could serialize and deserialize the
object, then you could do the processing in between those two steps. So
your problem is essentially equivalent to the serialization problem,
suggesting you look at Boost facilities for serialization, and require
"serializability" for the classes. Or even simpler, require "dumb
serialization" support: dump fields into vector, read 'em back from a
vector. After all you don't need more.

Another way is to do code generation. Of course that's also one
approach to serialization, for the same reasons. I regret to say that I
don't know very much about current tools, except that I think there's a
more or less complete C++ parser at SourgeForge (you could look into
building your own e.g. using Boost Phoenix, but it's a daunting task!).
What I can tell you of direct experience is that the g++ source code,
otherwise a natural starting point for build-your-own, is very complex.
And it's K&R C...

A third way is to note that your problem is very specialized compared to
general serialization. You're not interested in arbitrary structures,
only simple PODs. Thus, if you could define some simple descriptor,
then perhaps that would be acceptable for client code. One example of a
descriptor sufficient for your needs would be a list of offsets for the
fields in the struct, with a final offset just past the final field. I
think this would be my method of choice: not especially type safe, but
solving the practical problem at hand (perhaps the Boost preprocessor
facilities could be of help in automating descriptor generation).

Hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 19 '07 #8

P: n/a
Piyo wrote:
Ian Collins wrote:
>Piyo wrote:
>>There are a lot of ways to do introspection in C++. So far
the most portable one is to use macros. The idea is, as you
define classes you also put plain Macros that expand to code
that will help you do introspection. Here is a quick example:
I don't think so, not according to the traditional use of the term, to
be able to examine and possibly modify, an object at runtime. This
would permit a serialise function to determine the data members of a
class and automatically serialise them.


It depends on how you define introspection. Some only deal with the fact
that at run-time, you would like to be able to determine what are the
member functions and what are the member variables and or types and such
or even what are their superclasses too. From that point of view, if you
only plan on "querying introspection", then macros and Reflex can do
this for you. Please invest the time to go to the website and check it
out for yourself.
It looks interesting, but my development environment isn't supported :(

--
Ian Collins.
Feb 19 '07 #9

P: n/a
Dave Rahardja wrote:
On Mon, 19 Feb 2007 01:24:18 GMT, Piyo <cy*********@yahoo.comwrote:
>BTW, on second reading, you wanted to do Compile-time introspection:

I would look into heavy use of template metaprogramming to do this.
If that is too exotic for you, run-time introspection could be a good
alternative for you. (The stuff I originally posted.)

Good Luck!

(ignoring top-post faux pas)

I am conversant with template metaprogramming, but still find no way to do
compile-time introspection.

-dr
Is there a problem with run-time introspection? Because, based on your
previous example, you can do this.

// note I am making up the syntax for Seal Reflex since I don't have
// access to my work code right now. But I assure you, this can be done.
class ReflectedClass
{
public:
ReflectedClass()
{
MemberVar::iterator iter =
Reflex::Class("ReflectedClass").getMemberVars().be gin();
MemberVar::iterator end =
Reflex::Class("ReflectedClass").getMemberVars().en d();
for( ; iter!=end; ++iter )
{
// I just realized that you need to be careful since
// if it returns a non-POD, you need to recursively apply
// this function.
reverseEndian( iter->getVar() );
}
}

public:
int a;
float b;
double c;
// now later on, you can add as many member vars and you do not
// need to change the constructor at all.
};

If you don't like the constructor approach, your template function
will look like this:

template <typename Svoid reverseEndian(S& s)
{
// Reflex can take in a type I believe instead of a string
// for the Class constructor. Not sure. please check Seal docs.
// but hopefully you can go from Type to "name" via template
// type functions like show below.
MemberVar::iterator iter =
Reflex::Class(TypeMapper<S>::theName).getMemberVar s().begin();
MemberVar::iterator end =
Reflex::Class(TypeMapper<S>::theName).getMemberVar s().end();
for( ; iter!=end; ++iter )
{
// same warning as above applies
reverseEndianPOD( iter->getVar() );
}

}
Feb 19 '07 #10

P: n/a
Alf P. Steinbach wrote:
* Dave Rahardja:
>Is there a way to generate a series of statements based on the data
members of
a structure at compile time?

I have a function that reverses the endianness of any data structure:

/// Reverse the endianness of a data structure "in place".
template <typename T>
void reverseEndian(T&);

Using boost, it is possible to provide the default implementation for
all POD
types (i.e. simply reverse the bytes in the data item's representation).

Until today, I have purposely not provided the implementation for
structures,
forcing the user of the function to provide an implementation for each
structure, for example:

struct S
{
int a;
float b;
double c;
};

template <void reverseEndian(S& s)
{
// Function body -- can this be automated?
reverseEndian<>(s.a);
reverseEndian<>(s.b);
reverseEndian<>(s.c);
}

Is it possible to automatically generate the contents of the
specialization?
This calls for introspection (the language feature, not the Zen
philosophy),
and so far I have not found any way to do it, portable or otherwise.

No, you can't do what you want directly, at least as of the current
standard.

But yes, there other ways.

One way is to note that if you could serialize and deserialize the
object, then you could do the processing in between those two steps. So
your problem is essentially equivalent to the serialization problem,
suggesting you look at Boost facilities for serialization, and require
"serializability" for the classes. Or even simpler, require "dumb
serialization" support: dump fields into vector, read 'em back from a
vector. After all you don't need more.

Another way is to do code generation. Of course that's also one
approach to serialization, for the same reasons. I regret to say that I
don't know very much about current tools, except that I think there's a
more or less complete C++ parser at SourgeForge (you could look into
building your own e.g. using Boost Phoenix, but it's a daunting task!).
Some awesome people are nice enough to do this:

http://www.gccxml.org/HTML/Index.html

:)

What I can tell you of direct experience is that the g++ source code,
otherwise a natural starting point for build-your-own, is very complex.
And it's K&R C...

A third way is to note that your problem is very specialized compared to
general serialization. You're not interested in arbitrary structures,
only simple PODs. Thus, if you could define some simple descriptor,
then perhaps that would be acceptable for client code. One example of a
descriptor sufficient for your needs would be a list of offsets for the
fields in the struct, with a final offset just past the final field. I
think this would be my method of choice: not especially type safe, but
solving the practical problem at hand (perhaps the Boost preprocessor
facilities could be of help in automating descriptor generation).

Hth.,

- Alf
Feb 19 '07 #11

P: n/a
Ok, ok, I just got this cool idea and will need your help to
flesh it out since I am not a template wizard :)

Ok so let's look at boost::tuple. You can create essentially a
structure-like object with it except that the accessors are via numbers.
(http://www.boost.org/libs/tuple/doc/...ers_guide.html)

Then you can use a recursive template metaprogram to access each
element in the tuple. So it would look like something like this:

// for illustration purposes only
typedef boost::tuple<int,float,doubleYourTuple;

// recursive case
template< int N >
class test
{
public:
static void doIt( const YourTuple &t )
{
test<N-1>::doIt( t );
reverseEndian<>( t.get<N>() );
}
};

// basis case
template<>
class test<0>
{
public:
static void doIt( const YourTuple &t )
{
reverseEndian<>( t.get<0>() );
}
};

int
main()
{
YourTuple t( 0, 0.0f, 0.0 );
test<3>::doIt( t );
}

Granted, it isn't a struct, but hey it does get the job done
I think. :) So what's left here is to be able to take a struct
and map it to a tuple! Unfortunately, I don't see anything
that can automate it but you can do a manually defined template
type map.

struct foo
{
int a;
float b;
double c;
};

template<typename Tstruct TypeMapper;

template<>
struct TypeMapper<foo>
{
typedef boost::tuple<int,float,doubleYourTuple;
};

So what you can force your external people who make their
structs, to make the accompanying TypeMapper struct. You can
then, modify the template metaprogram to handle it this way:

template< int N, typename T >
class test
{
public:
static void doIt( typename T::YourTuple const &t )
{
test<N-1>::doIt( t );
reverseEndian<>( t.get<N>() );
}
};

// fix the basis case similarly

WHEW!!!! Did that make sense?! I know it has some more fleshing
out to do but I think, we can start from here!!

What do you think!!

:)
Dave Rahardja wrote:
On Mon, 19 Feb 2007 01:24:18 GMT, Piyo <cy*********@yahoo.comwrote:
>BTW, on second reading, you wanted to do Compile-time introspection:

I would look into heavy use of template metaprogramming to do this.
If that is too exotic for you, run-time introspection could be a good
alternative for you. (The stuff I originally posted.)

Good Luck!

(ignoring top-post faux pas)

I am conversant with template metaprogramming, but still find no way to do
compile-time introspection.

-dr
Feb 19 '07 #12

P: n/a
Piyo wrote:
Ok, ok, I just got this cool idea and will need your help to
flesh it out since I am not a template wizard :)

Ok so let's look at boost::tuple. You can create essentially a
structure-like object with it except that the accessors are via numbers.
(http://www.boost.org/libs/tuple/doc/...ers_guide.html)

Then you can use a recursive template metaprogram to access each
element in the tuple. So it would look like something like this:

// for illustration purposes only
typedef boost::tuple<int,float,doubleYourTuple;

// recursive case
template< int N >
class test
{
public:
static void doIt( const YourTuple &t )
{
test<N-1>::doIt( t );
reverseEndian<>( t.get<N>() );
}
};

// basis case
template<>
class test<0>
{
public:
static void doIt( const YourTuple &t )
{
reverseEndian<>( t.get<0>() );
}
};

int
main()
{
YourTuple t( 0, 0.0f, 0.0 );
test<3>::doIt( t );
}

Granted, it isn't a struct, but hey it does get the job done
I think. :) So what's left here is to be able to take a struct
and map it to a tuple! Unfortunately, I don't see anything
that can automate it but you can do a manually defined template
type map.

struct foo
{
int a;
float b;
double c;
};

template<typename Tstruct TypeMapper;

template<>
struct TypeMapper<foo>
{
typedef boost::tuple<int,float,doubleYourTuple;
};
Darn, jumped the gun there. In order for this to work, I need
a convert function:

struc TypeMapper<foo>
{
typedef boost::tuple<int, float, doubleYourTuple;
YourTuple convert( foo const &t )
{
// awww man, it's the exact thing you are trying to avoid!!!!
YourTuple temp;
temp.get<0>() = t.a;
...
}
};

Hmm ok, maybe structs do not work well but how about using boost::tuple
for your struct instead?? :)

>
So what you can force your external people who make their
structs, to make the accompanying TypeMapper struct. You can
then, modify the template metaprogram to handle it this way:

template< int N, typename T >
class test
{
public:
static void doIt( typename T::YourTuple const &t )
{
test<N-1>::doIt( t );
reverseEndian<>( t.get<N>() );
}
};

// fix the basis case similarly

WHEW!!!! Did that make sense?! I know it has some more fleshing
out to do but I think, we can start from here!!

What do you think!!

:)
Dave Rahardja wrote:
>On Mon, 19 Feb 2007 01:24:18 GMT, Piyo <cy*********@yahoo.comwrote:
>>BTW, on second reading, you wanted to do Compile-time introspection:

I would look into heavy use of template metaprogramming to do this.
If that is too exotic for you, run-time introspection could be a good
alternative for you. (The stuff I originally posted.)

Good Luck!

(ignoring top-post faux pas)

I am conversant with template metaprogramming, but still find no way
to do
compile-time introspection.

-dr
Feb 19 '07 #13

P: n/a
Alf P. Steinbach wrote:
* Dave Rahardja:
>Is there a way to generate a series of statements based on the data
members of
a structure at compile time?
No, you can't do what you want directly, at least as of the current
standard.
Does "at least as of the current standard" imply that something is
planned for the next standard, or was it just a general disclaimer?

I've often wanted this sort of capability, but I haven't heard about any
plans to include anything like that.

--
Alan Johnson
Feb 19 '07 #14

P: n/a
Alan Johnson wrote:
Alf P. Steinbach wrote:
>* Dave Rahardja:
>>Is there a way to generate a series of statements based on the data
members of
a structure at compile time?
No, you can't do what you want directly, at least as of the current
standard.

Does "at least as of the current standard" imply that something is
planned for the next standard, or was it just a general disclaimer?

I've often wanted this sort of capability, but I haven't heard about any
plans to include anything like that.
The C++ LWG has an open proposal addressing Reflection in C++ (both
compile and run time and the various ways it can be implemented).

Here is a link to the stuff the LWG is working on. Search for
Reflection in this page.

http://www.open-std.org/jtc1/sc22/wg...2006/n2122.htm

Too bad, it won't be included in C++09.....

Feb 19 '07 #15

This discussion thread is closed

Replies have been disabled for this discussion.