Search code examples
c++templatesboostboost-fusion

How can I get the type of a value in boost::fusion::map?


I am using boost fusion. I want to declare a template function that assigns to a field of a map and performs various other functions. I cannot for the life of me work out how to get the type of an element stored in a fusion::map. I am sure it is possible - I just can't fathom the documentation. I think I have two problems:

  1. I may not have the right headers included - compiler complains of incomplete type: boost::fusion::extension::value_of_data_impl
  2. I am not at all clear how to use result_of, value_of_data etc

To keep this really specific a minimal test case is shown below.

#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/fusion/include/container.hpp>
#include <boost/fusion/container.hpp>
#include <boost/fusion/iterator.hpp>

using std::string;

using namespace boost;

namespace fields {
  struct rgb;
  struct gray;
  struct keypoints;
  struct edges;
  struct objects;
}

typedef fusion::map<
  fusion::pair<fields::rgb,       string>,
  fusion::pair<fields::gray,      int>,
  fusion::pair<fields::keypoints, int>,
  fusion::pair<fields::edges,     int>,
  fusion::pair<fields::objects,   double>
> Fields;

Fields A_map;

template<typename field>
void Add(fusion::result_of::value_of_data<field> data) {
  fusion::at_key<field>(A_map) = data;
}

int main() {
  Add<fields::gray>(123);
}

The function Add should be declared to receive an argument which is the type of the gray field (int in the example).


Solution

  • @jv yes that is exactly the answer. Thanks very much.

    I've only being using fusion for a few hours and had not found that in the documentation (because the functions on iterators are visible at the top-level, whereas value_at_key only shows up when you dig down into Sequence/intrinsic/metafunctions)

    Also I needed to use typename and settled for simpler includes. The corrected code is:

    #include <string>
    #include <boost/fusion/include/sequence.hpp>
    #include <boost/fusion/include/map.hpp>
    
    using std::string;
    
    using namespace boost;
    
    namespace fields {
      struct rgb;
      struct gray;
      struct keypoints;
      struct edges;
      struct objects;
    }
    
    typedef fusion::map<
      fusion::pair<fields::rgb,       string>,
      fusion::pair<fields::gray,      int>,
      fusion::pair<fields::keypoints, int>,
      fusion::pair<fields::edges,     int>,
      fusion::pair<fields::objects,   double>
    > Fields;
    
    Fields A_map;
    
    template<typename field>
    void Add(typename fusion::result_of::value_at_key<Fields, field>::type data) {
      fusion::at_key<field>(A_map) = data;
    }