Call a member function using for_each
Asked Answered
A

2

6

This was my original code

#include "stdafx.h"
#include <string>
#include <list>
#include <algorithm>
using namespace std;


class testing
{
public:
    int value;
    testing(int v)
    {
        value = v;
    }

    int getval()
    {
        return(value);
    }

};

void func(testing& ob)
{
    printf("The value is %d\n", ob.value);
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::list<testing> testvar[3];

    testing t1(0);
    testing t2(1);
    testing t3(3);

    testvar[0].push_back(t1);
    testvar[0].push_back(t2);
    testvar[0].push_back(t3);

    std::for_each(testvar[0].begin(), testvar[0].end(), func);

    printf("Reached End");
    getchar();
    return 0;
}

I modified it to make func a member function and got weird compile errors, I searched online and someone had told use bind1st, bind2nd

#include "stdafx.h"
#include <string>
#include <list>
#include <algorithm>
using namespace std;

class testing
{
public:
int value;
testing(int v)
{
    value = v;
}

int getval()
{
    return(value);
}

};

class testing2
{
public:
    std::list<testing> testvar[3];

    void func(testing& ob)
    {
        printf("The value is %d\n", ob.value);
    }

    void driver()
    {
        std::for_each(testvar[0].begin(), testvar[0].end(), func);
    }

};



int _tmain(int argc, _TCHAR* argv[])
{
    testing2 testob;

    testob.driver();


    printf("Reached End");
    getchar();
    return 0;
}

So I modified the driver function to this

    void driver()
    {
std::for_each(testvar[0].begin(), testvar[0].end(),     std::bind1st(std::mem_fun(&testing2::func), this));
    }

I still get some weird compile erros, could someone please expain why we need to call a member function is such weird way..? and how does bind1st help..?

Actinia answered 2/8, 2013 at 0:6 Comment(4)
ssce please people are less inclined to answer when they see all this code for what is most likely a simple questionChadwickchae
I think the problem comes from void func(testing& ob) taking a reference vs. binder1st (the return type of bind1st) provides two overloads for operator(): one that takes a const second_argument& and one that takes a second_argument&. As the second argument of the return type of mem_fun(..) (which is mem_fun1_t) already is a reference, because func(testing&) takes a reference, these two overloads of operator() declare a function of the same signature.Spout
Why did you make func a member function?Several
If you can use C++11 or boost, you can (and should) use sehe's answer, otherwise you can try std::reference_wrapper (either from TR1 or write your own, it's simple) as a parameter for func.Spout
T
10

Use std::bind

 std::for_each(testvar[0].begin(), testvar[0].end(), std::bind(&testing2::func, this, std::placeholders::_1));

Or use std::bind/lambdas

 std::for_each(testvar[0].begin(), testvar[0].end(), [this](testing& ob) { func(ob); });

Full:

#include <string>
#include <list>
#include <algorithm>
using namespace std;

struct testing {
    int value;
    testing(int v) { value = v; }
    int getval() { return(value); }
};

struct testing2 {
    std::list<testing> testvar[3];

    void func(testing& ob) {
        printf("The value is %d\n", ob.value);
    }

    void driver() {
        auto f = std::bind(&testing2::func, this, std::placeholders::_1);
        std::for_each(testvar[0].begin(), testvar[0].end(), f);
        std::for_each(testvar[0].begin(), testvar[0].end(), [this](testing& ob) { func(ob); });
    }
};

int main() {
    testing2 testob;
    testob.driver();
    printf("Reached End");
}
Torture answered 2/8, 2013 at 0:21 Comment(2)
There is also std::mem_fn in C++11Executory
@Executory I don't think it applies here, as func is non-static member of a different class; a bind is requiredTorture
S
2

You can also use std::mem_fn for cleaner syntax like this:

std::for_each(testvar[0].begin(), testvar[0].end(), std::mem_fn(&testing::func));

Complete code:

#include <stdio.h>
#include <bits/stdc++.h>

class testing
{
public:
    testing(int v) : value(v) {}

    int getval() { 
        return(value);
    }

    void func()
    {
        printf("The value is %d\n", value);
    }

private:
    int value;
};

int main() {
    std::list<testing> testvar[3];

    testing t1(0);  
    testing t2(1);
    testing t3(3);

    testvar[0].push_back(t1);
    testvar[0].push_back(t2);
    testvar[0].push_back(t3);

    std::for_each(testvar[0].begin(), testvar[0].end(), std::mem_fn(&testing::func));

    return 0;
}
Sharpnosed answered 9/10, 2021 at 9:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.