Boost logo

Boost Users :

Subject: Re: [Boost-users] Get fields from struct
From: Vicente Botet (vicente.botet_at_[hidden])
Date: 2012-01-13 10:44:14


Matthijs Möhlmann wrote
>
> Hello all,
>
> I'm currently busy to get things like this working:
>
> struct person {
> std::string name;
> int age;
> };
>
> int main(int argc, char **argv) {
>
>
> person p;
> p.name = "Matthijs"
> p.age = 1234;
>
> std::string key = "name";
>
> // Now try to fetch the value based on the key string.
> std::cout << p.{key} << std::endl; // does not compile
>
> return 0;
> }
>
> Of course above doesn't work for obvious reasons.
>
> std::cout << "Name: " << boost::fusion::at_key<keys::name>(x) <<
> std::endl;
> std::cout << "Age: " << boost::fusion::at_key<keys::age>(x) <<
> std::endl;
>
> Now my question, is there maybe another way to achieve this?
>

I guess that what you want is a some kind of run-time reflection.

int main(int argc, char **argv) {
  person p;
  p.name = "Matthijs"
  p.age = 1234;
  std::string key = "name";
  std::cout << field_at_key(p, key) << std::endl;
  return 0;
}

The problem is that we don't know which type person_field_at_key should
return. We could type erase the result type and get it lazily when the value
is required.

The following maps to a field reference
 template <typename T>
 field_ref<T> field_at_key(T const& p, std::string const& key)
 {
   return field_ref<T>(p,key);
 }

We could overload an apply function specific for field_ref<person>

template <typename Visitor>
void apply(Visitor& v, field_ref<person> const&p)
{
   if (key=="name") v(p.get_person().name);
   else if (key=="age") v(p.get_person().age);
}

The preceding code could be generated by a macro, as it is done STRUCT_ADAPT

We could the define a OSTREAM visitor as follows

  template <typename OSTREAM>
  struct ostream_visitor {
    OSTREAM& os_;
    otream_visitor(OSTREAM& os) : _os(os)
    template <typename T>
    operator(T const& v) { os_ << v; }
  };

  template <typename OSTREAM, typename T>
  OSTREAM& operator<<(OSTREAM& os, field_ref<T> const& p)
  {
    ostream_visitor v(std::cout);
    apply(v,p);
    return *this;
  }

There are surely some boost related reflection libraries that I don't know
that it could be worth looking for as e.g. Boost.Mirror.

I don't know if you are looking for this behavior.

HTH,
Vicente

--
View this message in context: http://boost.2283326.n4.nabble.com/Get-fields-from-struct-tp4291964p4292528.html
Sent from the Boost - Users mailing list archive at Nabble.com.

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net