简体   繁体   中英

How to return boost::fusion::vector<x,y,z> elements to add to a std::array<boost::fusion::vector<x,y,z>>?

I have a std::array and a boost::fusion::vector<X, Y> which I want to pass in to func1() . This function will add a boost::fusion::vector<X, Y> instance to each std::array element.

I have to use fusion::fold() so that I can add the correct number of elements to the fusion::vector<X,Y> , right?

So I currently have something like this:

void func1(){
    boost::fusion::vector<X,Y> my_vec;
    std::array<boost::fusion::vector<X,Y> > my_array[10];
    func2(my_vec, my_array);
}

void func2(boost::fusion::vector<X,Y> my_vec, std::array<boost::fusion::vector<X,Y> > my_array){

    //THIS IS THE PART I AM UNSURE ABOUT
    for(int k=0; k<10; k++){
        //The first two parameters aren't so important- just included to show the idea
        my_array[k] = boost::fusion::fold(my_vec, 1, some_struct);
    }
}

//This part is irrelevant
struct some_struct
{
    typedef int result_type;

    template<typename T>
    int operator()(int x, T& t) const
    {
        t = something(x);
        //Not sure if this part needs to return a boost::fusion::vector<X, Y>
        return x;
    }
};

The part I am unsure about is how to use the signature of my_vec in order to create multiple boost::fusion::vector<X,Y> instances and return them back so that I can add to the array in func2() .

Could somebody please advise?

EDIT - Just spotted I got the first parameter for fold() wrong, have amended my question.

I'm not sure I understood your question really well so first let's explain what fold is to try to clarify.

In general (not just for fusion) "folding" a function taking two parameters is applying it to each and every element of the vector and to the result of the application of the function to the previous element of the vector. The first element is being given the initial value.

So if I define the function to fold as A f(A, B) , the folding of this function will be equivalent to (for 4 elements):

f(f(f(f(A_initial_value, B_0), B_1), B_2), B_3);

(capitalized prefix is there just to enforce type)

Now, more precisely fusion fold . It will fold the function on all the elements inside the boost::fusion::vector<> . As a boost::fusion::vector<X, Y> is equivalent to a std::tuple<X,Y> it will call f on different types:

A_final_value = f(A_initial_value, X_value), Y_value);

So, when you do:

my_array[k] = boost::fusion::fold(my_vec, 1, some_struct);

my_array[k] will receive an numeric value, and that won't compile since you've defined it as fusion::vector<X,Y>

So having trying to clarify fold , I would say no to your question, but I admit that I do not understand what you mean by "add the correct number of elements to the fusion::vector<X,Y> ".

EDIT: Updating according what've been said in comment. The goal isto generate a fibonacci sequence in your std::array<fusion::vector<int, int, int, int>> such as walking each vector of the array will give the fibonacci in the right order.

Using fusion you have to pass a state while iterating through the elements of the vector and so fold was a good choice.

Here is my suggestion for this (but starting the fibonacci sequence at the second element and not the first, cause I didn't bother to handle the special case... sorry :) ):

template <typename Value>
struct Generator
{
  // Easier to read and mandatory for fold
  typedef typename std::tuple<Value, Value> result_type;

  // The function that generate the fibonacci and update the Value  
  result_type operator()(result_type previous, Value& elem) const
  {
    elem = std::get<0>(previous) + std::get<1>(previous);
    return std::make_tuple(std::get<1>(previous), elem);
  }
};

// Use template to be a bit more generic on array size and vector type
template <typename Vector, size_t array_size, typename Value>
void func2(std::array<Vector, array_size>& array, std::tuple<Value, Value> init)
{
  // The state that will be fed across the fold function
  auto previous = init;
  for (auto& vect: array)
  {        
    // Generate the fibonnaci value for every element of the vector starting
    // from where the state is. The return value of fold is the new state
    previous = boost::fusion::fold(vect, previous, Generator<Value>());
  }
}

// Tool to print the vector
struct Printer
{
  template <typename Elem>
  void operator()(const Elem& elem) const
  {
    std::cout << elem << std::endl;
  }
};

// Use template to be a bit more generic on array size and vector type
template <typename Vector, size_t array_size, typename Value>
void func1(std::tuple<Value, Value> init)
{    
  // Create the vector
  std::array<Vector, array_size> array;

  // FIll it with fibonacci
  func2(array, init);

  // Print it
  for (auto vect: array)
  {        
    boost::fusion::for_each(vect, Printer());
  }   
}

http://rextester.com/XCXYX58360

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM