Use of a functor on for_each

前端 未结 4 977
陌清茗
陌清茗 2021-01-05 05:34

Why does the for_each call on functor doesn\'t update sum::total at the end?

struct sum
{
    sum():total(0){};
    int total;

            


        
相关标签:
4条回答
  • 2021-01-05 05:48

    for_each receives a copy of your functor by value. Even after that, it's free to copy it, but does return a copy.

    OTOH, you're simply trying to re-invent std::accumulate, which will do the job much more easily:

    int total = std::accumulate(arr, arr+6, 0);
    cout << total << endl; 
    
    0 讨论(0)
  • 2021-01-05 05:52

    Because the s which you pass to the for_each is by value. for_each accepts it by value!

    In C++0x, you can solve this problem with for_each as,

    int sum  = 0;
    std::for_each(arr, arr+6, [&](int n){ sum += n; });
    std::cout << sum ;
    

    Output:

    15
    

    Demo at ideone : http://ideone.com/s7OOn


    Or you can simple write in the std::cout itself:

    std::cout<<std::for_each(arr,arr+6,[&](int n)->int{sum += n;return sum;})(0);
    

    Run : http://ideone.com/7Hyla

    Note such different syntax is okay for learning purpose, as to how std::for_each works, and what it returns, but I would not recommend this syntax in real code. :-)


    In C++, you can write user-defined conversion function in the functor as,

    struct add
    {
        int total;
        add():total(0){};
        void operator()(int element)  {  total+=element;  }
        operator int() { return total ; }
    };
    
    int main()
    {
        int arr[] = {0, 1, 2, 3, 4, 5};
        int sum = std::for_each(arr, arr+6, add());
        std::cout << sum;
    }
    

    It's slightly different version from Erik second solution : http://ideone.com/vKnmA

    0 讨论(0)
  • 2021-01-05 05:54

    This happens due to std::for_each requires the functor to be passed by value . A workaround for your solution:

    struct sum
    {
        sum():total(0){};
        int total;
        sum(sum & temp)
        {
            total = temp.total;
        }
        void operator()(int element) 
        { 
           total+=element; 
        }
    };
    
    int main()
    {
        sum s;
    
        int arr[] = {0, 1, 2, 3, 4, 5};
        s = std::for_each(arr, arr+6, s);  // result of for_each assigned back to s
        cout << s.total << endl; // prints total = 0;
    }
    
    0 讨论(0)
  • 2021-01-05 06:11

    for_each takes the functor by value - so it is copied. You can e.g. use a functor which is initialized with a pointer to an external int.

    struct sum
    {
        sum(int * t):total(t){};
        int * total;
    
        void operator()(int element)
        {
           *total+=element;
        }
    };
    
    int main()
    {
        int total = 0;
        sum s(&total);
    
        int arr[] = {0, 1, 2, 3, 4, 5};
        std::for_each(arr, arr+6, s);
        cout << total << endl; // prints total = 15;
    }
    

    Or you can use the return value from for_each

    struct sum
    {
        sum():total(0){};
        int total;
    
        void operator()(int element) 
        { 
           total+=element; 
        }
    };
    
    int main()
    {
        sum s;
    
        int arr[] = {0, 1, 2, 3, 4, 5};
        s = std::for_each(arr, arr+6, s);
        cout << s.total << endl; // prints total = 15;
    }
    
    0 讨论(0)
提交回复
热议问题