Thread: Problem using std::for_each

  1. #1
    Registered User
    Join Date
    Nov 2006
    Posts
    519

    Problem using std::for_each

    Hi,

    is it somehow possible to pass param_1 to the function used by std::for_each?

    Code:
    std::vector<T> myCollection;
    T t;
    myCollection.push_back(t);
    
    
    
    void function(T& _t)
    {
       _t.a_member(param_1); // can that param_1 somehow be transfered here?
                                          // passing to function is not allowed, because then
                                          // for_each can't use function because of the wrong signature
    }
    
    
    void do_something(T param_1)
    {
        std::for_each(myCollection.begin(), myCollection.end(), function);
    }
    Thank you in advance!

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Sure - take a look at the mem_fun example on MSDN where "mem_fun1" and "bind2nd" are used to call lessconst().

    http://msdn2.microsoft.com/en-us/lib...7y(vs.80).aspx

    gg

  3. #3
    Registered User
    Join Date
    Nov 2006
    Posts
    519
    Thank you. Would it also work somehow using two or more parameters?

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I'm only guessing, but couldn't "bind2nd" use a "pair" or "pointer to struct/class" as the second parameter, which would give you "any" number of parameters as the second parameter.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Personally, I don't use mem_fun1. I'd rather skip for_each() and iterate the objects myself. The code "looks" more straight forward that way - to me anyways.

    gg

  6. #6
    Registered User
    Join Date
    Nov 2006
    Posts
    519
    unfortunately I can't even get this simple code using just one parameter to compile:

    Code:
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <functional>
    #include <algorithm>
    
    struct A
    {
    	void print_sum(int x, int y) const
    	{
    		printf("%d\n",x+y); 
    	}
    };
    
    void call_print_sum( const A& a, int z)
    {
    	a.print_sum(1,z);
    }
    
    void worker_function(int x, int y)
    {
    	std::vector<A> vec;
    	A a1, a2, a3;
    	vec.push_back(a1);
    	vec.push_back(a2);
    	vec.push_back(a3);
    	
    	std::for_each( vec.begin(), vec.end(), std::bind2nd(call_print_sum, 3) );
    	
    }
    
    int main()
    {
    	worker_function(3,7);
    }

    The linker says:

    Code:
    make all 
    Building file: ../main.cpp
    Invoking: GCC C++ Compiler
    g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o"main.o" "../main.cpp"
    /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_function.h: In instantiation of ‘std::binder2nd<void ()(const A&, int)>’:
    ../main.cpp:28:   instantiated from here
    /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_function.h:429: error: ‘void ()(const A&, int)’ is not a class, struct, or union type
    /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_function.h:432: error: ‘void ()(const A&, int)’ is not a class, struct, or union type
    /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_function.h:435: error: ‘void ()(const A&, int)’ is not a class, struct, or union type
    /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_function.h:439: error: ‘void ()(const A&, int)’ is not a class, struct, or union type
    /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_function.h:445: error: ‘void ()(const A&, int)’ is not a class, struct, or union type
    /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_function.h:431: error: field ‘std::binder2nd<void ()(const A&, int)>::op’ invalidly declared function type
    /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_function.h: In function ‘std::binder2nd<_Operation> std::bind2nd(const _Operation&, const _Tp&) [with _Operation = void ()(const A&, int), _Tp = int]’:
    ../main.cpp:28:   instantiated from here
    /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_function.h:454: error: ‘void ()(const A&, int)’ is not a class, struct, or union type
    /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_function.h:455: error: ‘void ()(const A&, int)’ is not a class, struct, or union type
    /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_algo.h: In function ‘_Function std::for_each(_InputIterator, _InputIterator, _Function) [with _InputIterator = __gnu_cxx::__normal_iterator<A*, std::vector<A, std::allocator<A> > >, _Function = std::binder2nd<void ()(const A&, int)>]’:
    ../main.cpp:28:   instantiated from here
    /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_algo.h:159: error: no match for call to ‘(std::binder2nd<void ()(const A&, int)>) (A&)’
    make: *** [main.o] Error 1
    Does anybody know why?

  7. #7
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    I got that to compile (MS Visual Studio 2008) by making a couple changes:
    Code:
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <functional>
    #include <algorithm>
    
    struct A
    {
    	void print_sum(int x, int y) const
    	{
    		printf("&#37;d\n",x+y); 
    	}
    };
    
    void call_print_sum( const A a, int z) // Changed to not use a reference
    {
    	a.print_sum(1,z);
    }
    
    void worker_function(int x, int y)
    {
    	std::vector<A> vec;
    	A a1, a2, a3;
    	vec.push_back(a1);
    	vec.push_back(a2);
    	vec.push_back(a3);
    	
    	std::for_each( vec.begin(), vec.end(), std::bind2nd(std::ptr_fun(call_print_sum), 3) );
    	
    }
    
    int main()
    {
    	worker_function(3,7);
    }
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Use the modern Boost binders.

    Code:
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <algorithm>
    
    #include <boost/bind.hpp>
    
    struct A
    {
    	void print_sum(int x, int y) const
    	{
    		printf("&#37;d\n",x+y); 
    	}
    };
    
    void worker_function(int x, int y)
    {
    	std::vector<A> vec;
    	A a1, a2, a3;
    	vec.push_back(a1);
    	vec.push_back(a2);
    	vec.push_back(a3);
    	
    	std::for_each( vec.begin(), vec.end(), boost::bind(&A::print_sum, _1, 1, 3) );
    }
    
    int main()
    {
    	worker_function(3,7);
    }
    You may have to qualify _1 with the boost namespace, too.

    The bind component is also part of the TR1 extensions, if your compiler has them. (GCC 4.2, for example.)
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    Registered User
    Join Date
    Nov 2006
    Posts
    519
    Thank you, that compiled for me also.

    Some C++ authors I read give advice like "prefer standard algorithm to hand written loops". But this seems pretty uncomfortable beside the absolute standard case. Also, without the possibility to CBR, it's not as efficient as a hand written loop. (ok, real world examples would use a vector<shared_ptr<A> > instead a vector<A> so this doesn't matter).

    Do the people here with lot of c++ experience follow that advice in general?

  10. #10
    Registered User
    Join Date
    Nov 2006
    Posts
    519
    Ah, thanks CornedBee, I read it to late. what works nice and looks a lot better

  11. #11
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by pheres View Post
    Do the people here with lot of c++ experience follow that advice in general?
    Yes, I always try to avoid hand-written loops when I stop to think about it

    That may well change with the C++09 for-each loop. Java-style convenience, C++-style zero overhead.
    Code:
    for(const A &a : vec) {
      a.print_values(1, 3);
    }
    What the hell is CBR?
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  12. #12
    Registered User
    Join Date
    Nov 2006
    Posts
    519
    Quote Originally Posted by CornedBee View Post
    Yes, I always try to avoid hand-written loops when I stop to think about it
    I guess that just means "yes". Unfortunately I've always a hard time understanding humor in english texts.

    That loop style looks nice! "CBR, CBV, CBA" means call-by-reference, -value, -address. I thought that abbreviations are common, but a check at WP (wikipedia ) showed they are not. I forgot from where I've them, maybe I just created them myself without knowing it.

  13. #13
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    It means yes, but I have to think about doing it consciously. The fact that I write a lot of code in Java, too, means that I tend to reduce my code to the common denominator of the two languages when I'm in the flow. Since Java doesn't have algorithms (and if it had, they'd be inefficient), that means that unless I remember that I'm writing C++, I'm more likely to use a hand-written for loop.

    Pretty much everything about a for-each can be inlined and optimized away by the compiler. Some compilers may have difficulties recognizing that the member function pointer is actually a constant, though, which would lead to an inefficient indirect call. You'd have to examine the assembly.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  14. #14
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by pheres View Post
    Some C++ authors I read give advice like "prefer standard algorithm to hand written loops". But this seems pretty uncomfortable beside the absolute standard case. Also, without the possibility to CBR, it's not as efficient as a hand written loop.
    If you mean call by reference, there is no issue. Just use boost::ref() or boost::cref() to reference-ify the parameters to bind().

    (ok, real world examples would use a vector<shared_ptr<A> > instead a vector<A> so this doesn't matter).
    Oh god I certainly hope not. Unless you specifically need polymorphic behavior, it's always better to hold objects by value in containers.

  15. #15
    Registered User
    Join Date
    Nov 2006
    Posts
    519
    Quote Originally Posted by brewbuck View Post
    If you mean call by reference, there is no issue. Just use boost::ref() or boost::cref() to reference-ify the parameters to bind().
    Ok, thank you. The quoted statement did refer to the example given by hk_mp5kpdw using std::bind2nd. It was written before I saw what CornedBee wrote about boost:bind.

    Quote Originally Posted by brewbuck View Post
    Oh god I certainly hope not. Unless you specifically need polymorphic behavior, it's always better to hold objects by value in containers.
    What exactly is the drawback using containers of pointers?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help understanding a problem
    By dnguyen1022 in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2009, 04:21 PM
  2. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  3. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  4. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  5. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM