 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
ralph Guest
|
Posted: Fri Aug 05, 2005 3:13 pm Post subject: std::map functors |
|
|
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
|
Posted: Sat Aug 06, 2005 9:56 am Post subject: Re: std::map functors |
|
|
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
|
Posted: Sat Aug 06, 2005 11:23 am Post subject: Re: std::map functors |
|
|
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
|
Posted: Sun Aug 07, 2005 1:30 am Post subject: Re: std::map functors |
|
|
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
|
Posted: Sun Aug 07, 2005 1:32 am Post subject: Re: std::map functors |
|
|
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
|
Posted: Sun Aug 07, 2005 1:40 am Post subject: Re: std::map functors |
|
|
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
|
Posted: Sun Aug 07, 2005 1:41 am Post subject: Re: std::map functors |
|
|
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
|
Posted: Wed Aug 10, 2005 9:55 am Post subject: Re: std::map functors |
|
|
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
|
Posted: Wed Aug 10, 2005 9:59 am Post subject: Re: std::map functors |
|
|
(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
|
Posted: Thu Aug 11, 2005 7:21 am Post subject: Re: std::map functors |
|
|
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 |
|
 |
|
|
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
|
|