C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

std::map functors

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
ralph
Guest





PostPosted: Fri Aug 05, 2005 3:13 pm    Post subject: std::map functors Reply with quote



Hi,

I'm trying to use algorithms instead of hand-written loops (mostly
because Scott Meyers told me so...).

There a couple of standard functors that I can reuse and I already have
lots of self-written functors.

Now I'd like to use these functors not only with strings, vectors,
lists, sets etc. I want to use them with maps. My problem is that the
standard algorithms feed the functors with objects of type
map::value_type. But the functors need map::value_type.second. Is there
a standard adapter or do I have to write every functor twice?

TIA
Ralph


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Alexander Reinhard
Guest





PostPosted: Sat Aug 06, 2005 9:56 am    Post subject: Re: std::map functors Reply with quote



ralph wrote:

Quote:
Hi,

I'm trying to use algorithms instead of hand-written loops (mostly
because Scott Meyers told me so...).

There a couple of standard functors that I can reuse and I already have
lots of self-written functors.

Now I'd like to use these functors not only with strings, vectors,
lists, sets etc. I want to use them with maps. My problem is that the
standard algorithms feed the functors with objects of type
map::value_type. But the functors need map::value_type.second. Is there
a standard adapter or do I have to write every functor twice?

It's not a Standard, but might work with many STL-implementations based on

SGI's implementation: http://www.sgi.com/tech/stl/select2nd.html.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Carl Barron
Guest





PostPosted: Sat Aug 06, 2005 11:23 am    Post subject: Re: std::map functors Reply with quote



ralph <ralph.peterson (AT) gmx (DOT) net> wrote:

Quote:
Hi,

I'm trying to use algorithms instead of hand-written loops (mostly
because Scott Meyers told me so...).

There a couple of standard functors that I can reuse and I already have
lots of self-written functors.

Now I'd like to use these functors not only with strings, vectors,
lists, sets etc. I want to use them with maps. My problem is that the
standard algorithms feed the functors with objects of type
map::value_type. But the functors need map::value_type.second. Is there
a standard adapter or do I have to write every functor twice?

TIA
Ralph

you can write one functor like

template <class Pair>
struct select2nd
{
typename Pair::second_type operator () (const Pair &x) const
{ return x.second;}
};

and use boost::transform_iterator with this functor to pass a sequence
of the second members to your existing functor in the various
algorithms.
[off the cyff boost not on this machine to test it]

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Zhenghui Zhou
Guest





PostPosted: Sun Aug 07, 2005 1:30 am    Post subject: Re: std::map functors Reply with quote

boostbind boost::lambda can help you. In fact, I suggest to deprecate
the stl functors in newer codes, they introduce more burden. As the
answer will be:

#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

struct Func() {
void operator(some_type);
};

void func(some_type);

typedef map<...>::value_type value_type;

stl::for_each(values.begin()
, values.end()
, boost::bind<void>(Func(),
boost::bind(
boost::function<int(std::map(
boost::lambda::unlambda(boost::lambda::bind(&std::map<int,
int>::value_type::second, boost::lambda::_1))
)
, _1
)
)
);

or

std::for_each(values.begin()
, values.end()
, boost::lambda::bind<void>(func
, boost::lambda::bind(&std::map<int, int>::value_type::second,
boost::lambda::_1)
)
);

or

Func f;
std::for_each(values.begin()
, values.end()
, boost::lambda::bind<void>(boost::ref(f) // or boost::lambda::var(f)
, boost::lambda::bind(&std::map<int, int>::value_type::second,
boost::lambda::_1)
)
);


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
YUY0x7
Guest





PostPosted: Sun Aug 07, 2005 1:32 am    Post subject: Re: std::map functors Reply with quote

Hey,
What algorithm functions are you talking about? Is it just for_each, or
in general? To make the functors use the second member of the map
value_type, you can create another functor around it. Something along
the lines of this:

#include <iostream>
#include <string>
#include <map>
#include <algorithm>

using namespace std;

template <typename ReturnType, typename Functor>
struct UseSecondFunctor
{
Functor m_functor;

UseSecondFunctor(Functor functor) : m_functor(functor) {}

template <typename Pair>
ReturnType operator()(Pair const & pair) { return
m_functor(pair.second); }
};

template <typename ReturnType, typename Functor>
UseSecondFunctor<ReturnType, Functor> UseSecond(Functor functor)
{
return UseSecondFunctor<ReturnType, Functor>(functor);
}

void some_func(string const& x)
{
cout << x << endl;
}

int main()
{
map mymap[0] = "hello";
mymap[1] = "Ralph";
mymap[2] = "Bye";
for_each(mymap.begin(), mymap.end(), UseSecond<void>(some_func));
}

That works great, though I don't know if there's another better way..

Hope that helps,
George Faraj


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Howard Hinnant
Guest





PostPosted: Sun Aug 07, 2005 1:40 am    Post subject: Re: std::map functors Reply with quote

In article <1123240924.784655.239290 (AT) f14g2000cwb (DOT) googlegroups.com>,
"ralph" <ralph.peterson (AT) gmx (DOT) net> wrote:

Quote:
Hi,

I'm trying to use algorithms instead of hand-written loops (mostly
because Scott Meyers told me so...).

There a couple of standard functors that I can reuse and I already have
lots of self-written functors.

Now I'd like to use these functors not only with strings, vectors,
lists, sets etc. I want to use them with maps. My problem is that the
standard algorithms feed the functors with objects of type
map::value_type. But the functors need map::value_type.second. Is there
a standard adapter or do I have to write every functor twice?

With the not-quite-yet-released boost bind you'll be able to:

typedef map<int,int> Map;
Map m;
m.insert(make_pair(1, 2));
m.insert(make_pair(2, 0));
m.insert(make_pair(3, 1));
Map::iterator i =
find_if(m.begin(), m.end(),
bind(&Map::value_type::second, _1) == 0);

In the current boost::bind, and also using std::tr1::bind, it is not
quite as convenient:

Map::iterator i =
find_if(m.begin(), m.end(),
bind(
equal_to<Map::mapped_type>(),
bind(&Map::value_type::second, _1),
0
)
);

-Howard

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
sga
Guest





PostPosted: Sun Aug 07, 2005 1:41 am    Post subject: Re: std::map functors Reply with quote

Hi Ralph :

I use these all the time for maps, std::pair< whatever >, etc. This is
similar to another response to your post but you'll notice that the
outermost struct is _not_ a template, rather the inner function is.
This makes its usage _much_ easier because you don't need to explicitly
specify the template parameter for the functor.

Depending on the compiler you're using (ie gcc 3.x, intel 8, vc,
borland) you may or may not need the explicit "typename" keywords. VC
tends to be the most forgiving ...

These are two I use frequently :

struct TuPairFirst
{
template < typename Pair >
const typename Pair::first_type& operator()( const Pair& the_pair )
const
{
return the_pair.first;
}
};

struct TuPairSecond
{
template < typename Pair >
const typename Pair::second_type& operator()( const Pair& the_pair
) const
{
return the_pair.second;
}
};



You may also want functional implementations of these :

template < typename Pair >
inline typename Pair::first_type PairFirst( const Pair& the_pair )
{
return the_pair.first;
}

template < typename Pair >
inline typename Pair::second_type PairSecond( const Pair& the_pair )
{
return the_pair.second;
}


Best of luck;
sga


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Tokyo Tomy
Guest





PostPosted: Wed Aug 10, 2005 9:55 am    Post subject: Re: std::map functors Reply with quote

I am interested in boost::transform_iterator, played around with it for
a while, and I found the second element of the pair could not mutated,
even if I changed the slect2nd as below:

template <class Pair>
struct select2nd
{
typename Pair::second_type& operator () (Pair &x) const
{ return x.second;}
};

Is there any workaround of impossible?

I failed the code below. I used macros to save typing:

[code]

#include <map>
#include <numeric>
#include <iostream>
#include <algorithm>
#include <boost/iterator/transform_iterator.hpp>


template <class Pair>
struct select2nd: std::unary_function<Pair&, typename
Pair::second_type>
{
typename Pair::second_type operator () ( const Pair &x) const
{ return x.second;}
};

#define second(mapT, iterator)
boost::make_transform_iterator(iterator, select2nd<mapT::value_type>())


#define map_print(mapT, m)
std::cout << #m<< ": ";
std::copy(second(mapT, m.begin()), second(mapT, m.end()),

std::ostream_iterator std::cout << std::endl


int main() {

typedef std::map Map m;
m.insert(std::make_pair(1, 2));
m.insert(std::make_pair(2, 0));
m.insert(std::make_pair(3, 1));

map_print(Map, m);

std::cout << std::accumulate(second(Map, m.begin()), second(Map,
m.end()), 3) << std::endl; //ok
std::partial_sum(second(Map, m.begin()), second(Map, m.end()),
second(Map, m.begin())); //error

map_print(Map, m);

return 0;
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Tokyo Tomy
Guest





PostPosted: Wed Aug 10, 2005 9:59 am    Post subject: Re: std::map functors Reply with quote

(continued from my previous post)

Excuse me. I found a way to change the second element of pair by
changing the select2nd as below.


[code}

#include <numeric>
#include <iostream>
#include <algorithm>
#include <boost/iterator/transform_iterator.hpp>


template <class Pair>
struct select2nd: std::unary_function<Pair&, typename
Pair::second_type&> // modifed
{
typename Pair::second_type& operator () ( Pair &x) const
{ return x.second;}
};

#define second(mapT, iterator)
boost::make_transform_iterator(iterator, select2nd<mapT::value_type>())


#define map_print(mapT, m)
std::cout << #m<< ": ";
std::copy(second(mapT, m.begin()), second(mapT, m.end()),

std::ostream_iterator std::cout << std::endl


int main() {

typedef std::map Map m;
m.insert(std::make_pair(1, 2));
m.insert(std::make_pair(2, 0));
m.insert(std::make_pair(3, 1));

map_print(Map, m);

std::cout << std::accumulate(second(Map, m.begin()), second(Map,
m.end()), 3) << std::endl; //ok
std::partial_sum(second(Map, m.begin()), second(Map, m.end()),
second(Map, m.begin())); //now ok

map_print(Map, m);

return 0;
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ralph Zhang
Guest





PostPosted: Thu Aug 11, 2005 7:21 am    Post subject: Re: std::map functors Reply with quote


my solution (use only boost::bind and boost::function, easy to fit the
coming C++0x):

struct Func
{
void operator()(int i)
{
std::cout << i << " ";
}
};

int main()
{
std::map values[0] = 100;
values[1] = 101;
values[2] = 102;
values[3] = 103;

std::for_each(values.begin(), values.end(),
boost::bind(boost::function<void(int)>(Func()),
boost::bind(&std::map<int,int>::value_type::second, _1)
)
);
}

The use of boost::function is optional, but you'll have to typedef
result_type then, as boost::bind won't deduce it for you.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.