Topic: for each member of a structure/class ?


Author: nagle@animats.com (John Nagle)
Date: Fri, 28 Dec 2007 21:46:27 GMT
Raw View
Martijn Meijering wrote:
> Roman.Perepelitsa@gmail.com wrote:

>  > What would be really useful is something
>> like restor suggested in this thread: ability to get tuple
>> of references to all members of a struct/class.
>
> Agreed.
>
>> But
>> I'm not aware of any proposals regarding this subject.
>
> Neither am I, but I think it would be quite an important addition. Not
> quite as important as modules, but still quite important.

     I'd once given this some thought.  But in a language that doesn't
have tuples, and barely has arrays with known length, it's difficult to
create an appropriate data structure.

     I suppose something could be hacked up involving recursive template
instantiation.   One could have a primitive like like "typeof_field(T,N)",
returning the type of field N of object T.  Then, using recursive
templates, one could iterate through the fields.  It might also be
useful to have "field_count(T)", for termination checking.

     This would be useful for automatically generating marshalling code
at compile time.  That can be a substantial win, because marshalling code
usually consists of trivial copies slowed down by the run time machinery
which invokes them.

     John Nagle
     Animats

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Mathias Gaunard <loufoque@gmail.com>
Date: Fri, 4 Jan 2008 11:33:37 CST
Raw View
On 28 d   c 2007, 22:46, na...@animats.com (John Nagle) wrote:

>      I'd once given this some thought.  But in a language that doesn't
> have tuples, and barely has arrays with known length, it's difficult to
> create an appropriate data structure.

There is no problem with C++ tuples. They're simply automatically-
generated structures with some reflection information (ability to know
the number of members, ability to retrieve the i-th member, ability to
retrieve the type of the i-th member).
But anyway why would you want to use tuples to expose full class
reflection? They're not enough to support all of the reflection needs
of C++ classes (member variables, overloaded member functions, static
member variables and functions, typedefs).

I believe this design is fairly good:

template<typename T>
struct reflection {};

template<> struct reflection<MyClass>
{
     typedef mpl::map<
         mpl::pair<
             mpl::vector_c<char, 'm', 'e', 'm', 'b', 'e', 'r', '1'>,

a_function_object_type_which_allows_to_get_the_member_and_exposes_its_type
         >,
         ....
     > member_variables;

     typedef .... member_functions; /* same as member_variables except
the function object must expose and allow to call multiple overloads
*/

     typedef .... typedefs; /* nothing more than a type -> type map */
     typedef .... static_member_functions; /* same as
member_functions, except we don't take an object in the functor
constructor */
     typedef .... static_member_variables; /* same as
member_variables, except we don't take an object in the functor
constructor */

     typedef .... constructors; /* a single function object */

     typedef .... base_classes; /* a list of base types */
};

I'd say only public interface needs to be exposed, but protected and
private interfaces could also be exposed in a reflection_protected/
private for example.

The only problem is how to expose the type of template member
functions.
Doing so would be quite complicated.

For example, to encode
template<int A, typename B> typename B::type func(B&, void*),

we could expose the template parameters and then construct an
expression tree for each element of the signature.

typedef mpl::vector<
    mpl::pair< mpl::vector_c<char, 'A'>, value_parameter<int> >,
    mpl::pair< mpl::vector_c<char, 'B'>, type_parameter >
> parameters;

typedef mpl::vector<
   static_var_bind< ref<1>, mpl::vector_c<char, 't', 'y', 'p', 'e'>
>,  /* ref<1> stands for second template parameter */
   add_ref< ref<1> >,
   type<void*>
> signature;

with appropriate types providing reflection:
- value_parameter and type_parameter
- ref and type
- static_var_bind, static_func_bind, add_ref, add_const, add_volatile,
add_pointer, and probably others, such as passing the parameter as a
parameter to another template or building a function type which
contains a parameter type.

Another simpler but less powerful way would be to expose the template
parameters and then allow the signature to be extracted given the
parameters.

typedef mpl::vector<
    mpl::pair< mpl::vector_c<char, 'A'>, value_parameter<int> >,
    mpl::pair< mpl::vector_c<char, 'B'>, type_parameter >
> parameters;

template<int A, typename B>
struct signature
{
   typedef typename B::type (B&, void*) type;
};

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]