Search code examples
c++boostboost-mplboost-fusion

Getting the index of boost::fusion::vector from a boost::mpl::vector


I started to play around with the boost fusion and mpl library and got stuck with a quite simple problem.

I declared the following types:

typedef boost::mpl::vector<char, int, long>   TypeVector;
typedef boost::fusion::vector<char, int, long> FusionVector_t;

Now I wanted to write a function that gets me the value from the FusionVector.

template<size_t N typename T>
T getValue(FusionVector_t fvec)
{
    return boost::fusion::at_c<N>(fvec);
}

The function works as expected but I would like to get the index from the boost::mpl vector and use it in this function and not pass it to the function as a template parameter. But I did not figure out so far how to do this.

Could someone give me a hint?


Solution

  • You can use the find algorithm to get an "iterator" pointing to the first occurence of a type in an MPL sequence. Something like:

    typedef boost::mpl::find<TypeVector, T>::type MplIter;
    

    and then query the fusion vector at that "iterator"'s position:

    return boost::fusion::at_c<MplIter::pos::value>(fvec);
    

    However, I don't see why you use the MPL vector at all. IIUC, you'd like to define getValue as:

    template<class T>
    T getValue(FusionVector_t fvec)
    {
      typedef boost::mpl::find<TypeVector, T>::type MplIter;
      return boost::fusion::at_c<MplIter::pos::value>(fvec);
    }
    

    which can work only if TypeVector and FusionVector_t "contain" the same sequence of types. In that case, why not only use FusionVector_t and write:

    template<class T>
    T getValue(FusionVector_t fvec)
    {
      return *boost::fusion::find<T>(fvec);
    }
    

    Moreover, if you want to use "T" as an "index" into the Fusion sequence, this only makes sense if a given type appears only once in the sequence. A fusion::set would thus seem more appropriate than a vector. In that case, you'd have:

    typedef boost::fusion::set<char, int, long> FusionSet_t;
    
    template<class T>
    T getValue(FusionSet_t fset)
    {
      return boost::fusion::at_key<T>(fset);
    }