for_each and functors

This is a discussion on for_each and functors within the C++ Programming forums, part of the General Programming Boards category; I want to use for_each to iterate over a series of sprites based on a predicate and then draw them. ...

  1. #1
    Registered User
    Join Date
    Jan 2007
    Posts
    330

    for_each and functors

    I want to use for_each to iterate over a series of sprites based on a predicate and then draw them. But I forgot how to use predicates. The only way I could think of was the following:


    Code:
    struct OpaqueTest
    {
    	void operator()(CSprite &sprite) 
    	{ 
    		if (sprite.GetOpacity() == ALPHA_OPAQUE)
    		{
    			sprite.Draw();
    		}
    	}
    };
    
    struct NonOpaqueTest
    {
    	void operator()(CSprite &sprite) 
    	{ 
    		if (sprite.GetOpacity() != ALPHA_OPAQUE)
    		{
    			sprite.Draw();
    		}
    	}
    };
    
    std::for_each(m_Sprites, m_Sprites + Size, OpaqueTest);
    std::for_each(m_Sprites, m_Sprites + Size, NonOpaqueTest);
    Can I compact the two functors into one and use some predicate in the for_each calls? Because as it is now I couldve just written out a for loop. The only thing different is the == and != in the functors.

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    You can parametrize the difference. Something like this:

    Code:
    #include <iostream>
    #include <algorithm>
    #include <functional>
    
    const int ALPHA_OPAQUE = 1;
    
    struct CSprite
    {
        int op; 
        int GetOpacity() const { return op; }
        void Draw() const {
            std::cout << op << '\n';
        }
    };
    
    template <class Func>
    struct OpaqueTest
    {
    	void operator()(CSprite &sprite) 
    	{ 
    		if (Func()(sprite.GetOpacity(), ALPHA_OPAQUE))
    		{
    			sprite.Draw();
    		}
    	}
    };
    
    
    int main()
    {
        const int Size = 4;
        CSprite m_Sprites[Size] = {{1}, {0}, {1}, {3}};
        std::for_each(m_Sprites, m_Sprites + Size, OpaqueTest<std::equal_to<int> >());
        std::for_each(m_Sprites, m_Sprites + Size, OpaqueTest<std::not_equal_to<int> >());
    }
    Personally I find that for_each does so little for you, that the trouble is not often worth it. (C++0x has auto keyword which makes writing the manual loop easier, as well as range-based for loop to begin with. So far I mostly use BOOST_FOREACH in more complicated cases.)
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #3
    Registered User
    Join Date
    Jan 2007
    Posts
    330
    seems complex indeed

Popular pages Recent additions subscribe to a feed

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21