Search code examples
c++boostboost-fusion

apply boost::fusion::for_each to boost::fusion::vector with mutable function object


I am trying to use boost::fusion::vector. However, I am in trouble with the very simple problem.

#include <iostream>
#include <string>

#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/algorithm.hpp>

using namespace std;

struct A{
    template <class T>
    void operator()(const T& t) {
        x++;
        cout << t << endl;
    }

    int x = 0;
};

int main(){
    A a;
    boost::fusion::vector<int, int, int> tuple{3,4,5};
    boost::fusion::for_each(tuple, a);
}

Note that the operator() of struct A modifies x in struct A. gcc 4.7.2 warns that ...\include\boost\fusion\algorithm\iteration\detail\for_each.hpp:77: error: passing 'const A' as 'this' argument of 'void A::operator()(const T&) [with T = int]' discards qualifiers [-fpermissive]

Is there a solution for this?


Solution

  • Well, I have not used boost::fusion, but from error message and example from docs, it seems that for_each expects const object. I.e. operator() should be const as well. However you will be unable to mutate object.

    Try this:

    void operator()(const T& t) const {
        cout << t << endl;
    }
    

    Edit:

    I've checked the sources (v. 1.53) and the declaration is for_each(Sequence& seq, F const& f). So there is really no way to modify object itself. The only options I see are

    either use static variables: static int x;

    or use pointers:

    struct A {
        template <class T>
        void operator()(const T& t) const {
            (*x)++;
            std::cout << t << std::endl;
        }
    
        int* x;
    };
    
    int main()
    {
        A a;
        a.x = new int;
        *(a.x) = 0;
        //...
    

    In this case be careful with coping A instances, as pointers will all point to the same location.