I am looking information about static reflection in C++. What are the
key concepts. Whether it will be included in the upcoming C++
standards?
I have seen some post on the newsgroup but they are old and most is on
runtime reflection.
To clarify I would like to tell what do I mean by static reflection
(maybe there is a more appropriate name for it?).
In my opinion static reflection is to provide (only in compile time):
mechanism that would allows templates to iterate through members of a
type, i.e.
- Iterate through fields, member functions and types of the class
e.g. first< fields<ClassA> >::type to obtain type of the first
field of ClassA
- iterate through bases of the class,
e.g. base<ClassA> or next< first< bases<ClassA> > >::type
- iterate through qualifiers of fields (in fact it is sort of
possible now) - but why not it more neater to avoid generation of
intermediate types.
- iterate through parameters of function
e.g. first< parameters<typeof(functionA)> >::type
- obtaining string literals such as names of fields, name of types,
name of qualifiers, name of parameter variables etc
e.g. type_literal( ClassA ) gives 'ClassA',
for struct ClassA { int _myField; };
name_literal< first< fields<ClassA> > > >::value gives
'_myField'
all in compile time
- additionally defining and using custom qualifiers/annotations in
type definitions, field and variable declarations and so on (in order
to be processed by reflection related templates)
e.g.
<code>
qualifier __non_serializable__;
qualifier __reflective__; // reached by name in runtime;
struct ClassA : public
Serializable<ClassA>, // e.g. produces all the code needed
to serialize fields
Reflective<ClassA> // e.g. adds interface that allows to
access all __reflective__ members using literals of their names
{
int field1;
void* __non_serializable__ field2; // indicate this field is
not to be serialized
void __reflective__ findMeByNameAndExec( int a );
};
</code>
- uniform access to information such as current class type (from its
declaration and all member functions, e.g. 'this_class' ), current
function/method type (from body of a function, e.g. 'function_type')
- similarly defined reflection for templates themselves
As you can see above all the change in the language would be addition
several
predefined templates and custom qualifiers.
There is of course plenty of possible applications, most obvious:
- generating object serialization/deserialization routines and
factories
- generating RPC intermediate functions (no more stubs and that awful
maintenance)
- automatic object dumping functions (just one liner to print out
complex object)
- automatic generation of adapter classes (imagine template that
produces a class
that provides all
the interface of the given class. imagine doing so in one liner
for whole inheritance tree of classes )
- runtime reflection could be founded on such defined static
reflection, so it would not need to be a standard
- object hierarchies
- means for static code checking (static assertions)
I am willing to learn more on that subject, share my thoughts.
If you have good links on that topic, your own ideas,
please let me know.
Maciej
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
mafjmafj (2)
|
7/31/2008 1:28:21 PM |
|
On 31 juil, 22:28, Mafj <mafjm...@googlemail.com> wrote:
> I am looking information about static reflection in C++. What are the
> key concepts. Whether it will be included in the upcoming C++
> standards?
The next standard introduces two new forms of compile-time reflection:
1) Concepts, which are most just syntactic sugar for (2)
2) SFINAE with full expression support
The well-known SFINAE technique in C++03 only works with static member
access depending on template parameters, but in C++0x you can use
whole expressions.
That is to say, if you write a function like this in C++0x
template<typename T1, typename T2>
auto add(const T1& t1, const T2& t2) -> decltype(t1 + t2)
{
return t1 + t2;
}
The function will not be visible if t1 + t2 is not a valid operation
with the types that were provided.
It should also work with meta-functions:
template<typename T1, typename T2, typename Enable = void>
struct is_addable
{
static const bool value = false;
};
template<typename T1, typename T2>
struct is_addable<T1, T2, decltype(T1() + T2())>
{
static const bool value = true;
};
> In my opinion static reflection is to provide (only in compile time):
>
> mechanism that would allows templates to iterate through members of a
> type, i.e.
> - Iterate through fields, member functions and types of the class
> e.g. first< fields<ClassA> >::type to obtain type of the first
> field of ClassA
> - iterate through bases of the class,
> e.g. base<ClassA> or next< first< bases<ClassA> > >::type
You can only do that, be it with C++03 or C++0x, by exposing that
information as compile-time data structures.
A Boost.MPL map of MPL strings to functor types seems like the right
thing to do. I had wanted to do some preprocessor to do that myself
for a while.
> - iterate through qualifiers of fields (in fact it is sort of
> possible now) - but why not it more neater to avoid generation of
> intermediate types.
Type traits already do that.
> - iterate through parameters of function
> e.g. first< parameters<typeof(functionA)> >::type
A boost library already does that, it was called function traits if I
remember correctly.
> - obtaining string literals such as names of fields, name of types,
> name of qualifiers, name of parameter variables etc
> e.g. type_literal( ClassA ) gives 'ClassA',
> for struct ClassA { int _myField; };
> name_literal< first< fields<ClassA> > > >::value gives
> '_myField'
> all in compile time
That information should obviously be available in the exposed data
aforementioned.
> - additionally defining and using custom qualifiers/annotations in
> type definitions, field and variable declarations and so on (in order
> to be processed by reflection related templates)
There is a way to put attribute on things in C++0x, but it's intended
for the compilers.
You'd have to expose those qualifiers along with the rest.
> - uniform access to information such as current class type (from its
> declaration and all member functions, e.g. 'this_class' ), current
> function/method type (from body of a function, e.g. 'function_type')
That seems of no use.
> - similarly defined reflection for templates themselves
Doesn't make sense.
The only thing that makes sense is having access to a list of members
in a class, their name, their type (might be difficult to expose), and
a way to call them.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Mathias
|
8/1/2008 12:38:58 PM
|
|
On Aug 1, 8:38 pm, Mathias Gaunard <loufo...@gmail.com> wrote:
> On 31 juil, 22:28, Mafj <mafjm...@googlemail.com> wrote:
>
> > I am looking information aboutstaticreflectionin C++. What are the
> > key concepts. Whether it will be included in the upcoming C++
> > standards?
>
> The next standard introduces two new forms of compile-timereflection:
> 1) Concepts, which are most just syntactic sugar for (2)
> 2) SFINAE with full expression support
>
> The well-known SFINAE technique in C++03 only works withstaticmember
> access depending on template parameters, but in C++0x you can use
> whole expressions.
>
> That is to say, if you write a function like this in C++0x
>
> template<typename T1, typename T2>
> auto add(const T1& t1, const T2& t2) -> decltype(t1 + t2)
> {
> return t1 + t2;
>
> }
>
> The function will not be visible if t1 + t2 is not a valid operation
> with the types that were provided.
>
> It should also work with meta-functions:
>
> template<typename T1, typename T2, typename Enable = void>
> struct is_addable
> {
> staticconst bool value = false;
>
> };
>
> template<typename T1, typename T2>
> struct is_addable<T1, T2, decltype(T1() + T2())>
> {
> staticconst bool value = true;
>
> };
That seems really useful.
> > In my opinionstaticreflectionis to provide (only in compile time):
>
> > mechanism that would allows templates to iterate through members of a
> > type, i.e.
> > - Iterate through fields, member functions and types of the class
> > e.g. first< fields<ClassA> >::type to obtain type of the first
> > field of ClassA
> > - iterate through bases of the class,
> > e.g. base<ClassA> or next< first< bases<ClassA> > >::type
>
> You can only do that, be it with C++03 or C++0x, by exposing that
> information as compile-time data structures.
Well, I know I can define appropriate metafunctions/traits myself,
however,
they would contain redundant information and they would require
maintenance.
> A Boost.MPL map of MPL strings to functor types seems like the right
> thing to do. I had wanted to do some preprocessor to do that myself
> for a while.
>
> > - iterate through qualifiers of fields (in fact it is sort of
> > possible now) - but why not it more neater to avoid generation of
> > intermediate types.
>
> Type traits already do that.
I think type traits deal only with existing qualifiers (by their
definition they cannot work with others).
If there was a way to create custom qualifiers and a way to process
them then it will be really good.
>
> > - iterate through parameters of function
> > e.g. first< parameters<typeof(functionA)> >::type
>
> A boost library already does that, it was called function traits if I
> remember correctly.
>
> > - obtaining string literals such as names of fields, name of types,
> > name of qualifiers, name of parameter variables etc
> > e.g. type_literal( ClassA ) gives 'ClassA',
> > for struct ClassA { int _myField; };
> > name_literal< first< fields<ClassA> > > >::value gives
> > '_myField'
> > all in compile time
>
> That information should obviously be available in the exposed data
> aforementioned.
Once again it is such a pain to maintain redundant data knowing that
compiler stores it all somewhere.
It would just a bit of good will to expose it for programmers.
>
> > - additionally defining and using custom qualifiers/annotations in
> > type definitions, field and variable declarations and so on (in order
> > to be processed byreflectionrelated templates)
>
> There is a way to put attribute on things in C++0x, but it's intended
> for the compilers.
> You'd have to expose those qualifiers along with the rest.
I know it is all possible by just defining extra traits for each
class. But once again maintenance.
Why all this information cannot be exposed by compiler in some neat
compiler-supported metafunctions.
>
> > - uniform access to information such as current class type (from its
> > declaration and all member functions, e.g. 'this_class' ), current
> > function/method type (from body of a function, e.g. 'function_type')
>
> That seems of no use.
Well, I agree there is typeof(*this), so 'this_class' keyword would
have no much use.
>
> > - similarly definedreflectionfor templates themselves
>
> Doesn't make sense.
Maybe one step at a time would be enough.
> The only thing that makes sense is having access to a list of members
> in a class, their name, their type (might be difficult to expose), and
> a way to call them.
Of course we need to include in this place class bases (which are also
a kind of members).
I still think that having custom qualifiers, attributes or annotations
(however we call them)
Would be a good thing to affect the way how metafunctions could
process class members.
Maybe the qualifiers should be tied to fields/members rather than to
their types.
How would you call them annotations? Attributes?
I will come up with an example shortly.
Thanks for your thoughts.
Maciej
{ Edits: quoted clc++m banner removed, please don't quote it. -mod }
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Mafj
|
8/4/2008 3:56:42 PM
|
|
On 4 ao�t, 23:56, Mafj <mafjm...@googlemail.com> wrote:
> Why all this information cannot be exposed by compiler in some neat
> compiler-supported metafunctions.
It can, it just isn't going to happen in the next standard.
The standardization process is long and complicated, and no one has
been working on that.
I think making a preprocessor that automatically generate reflection
data visible at compile-time is the best solution at the moment.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Mathias
|
8/4/2008 11:14:08 PM
|
|
|
3 Replies
321 Views
(page loaded in 0.02 seconds)
|