Reputation: 3437
I'm trying to use the transform algorithm (or any other part of the STL that would do the job) to change a sequence of ints. If the current element is more than 5, keep it. Else use 5.
This does not compile :
std::vector<int> vec;
vec.push_back(6);
vec.push_back(2);
vec.push_back(9);
vec.push_back(4);
vec.push_back(7);
std::transform(vec.begin(), vec.end(), vec.begin(), std::bind1st(std::max<int>(), 5));
I don't have access to C++11.
Upvotes: 2
Views: 253
Reputation: 310940
For this task the more appropriate algorithm is std::replace_if
. For example
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
int main()
{
std::vector<int> vec;
vec.push_back( 6 );
vec.push_back( 2 );
vec.push_back( 9 );
vec.push_back( 4 );
vec.push_back( 7 );
for ( std::vector<int>::size_type i = 0; i < vec.size(); i++ )
{
std::cout << vec[i] << ' ';
}
std::cout << std::endl;
std::replace_if( vec.begin(), vec.end(),
std::bind2nd( std::less<int>(), 5 ), 5 );
for ( std::vector<int>::size_type i = 0; i < vec.size(); i++ )
{
std::cout << vec[i] << ' ';
}
std::cout << std::endl;
return 0;
}
The output is
6 2 9 4 7
6 5 9 5 7
Upvotes: 3
Reputation: 545528
You unfortunately cannot use bind*
with function pointers directly. To work around this, you’d normally use std::ptr_fun
but in your case that won’t work either1. So the way forward is to wrap std::max
into a functor:
template <typename T>
struct max : std::binary_function<T, T, T> {
T operator ()(T value, T min) const {
return std::max(value, min);
}
};
Usage:
std::transform(vec.begin(), vec.end(), vec.begin(), std::bind2nd(max<int>(), 5));
1 It appears as if std::bind1st(std::ptr_fun(&std::max<int>), 5)
should work but unfortunately this template instantiation creates two identical operator()
overloads, since std::max
takes its arguments as const
.
Upvotes: 2
Reputation: 71899
Why do the two existing answers replace the perfectly good std::max
with identically implemented functions/functors with different names? std::max
is perfectly fine; it's the way you use the old binders that's wrong.
You say you don't have C++11. Do you have Boost? Boost.Bind will do the job:
std::transform(vec.begin(), vec.end(), vec.begin(),
boost::bind(&std::max<int>, _1, 5));
I can't remember what namespace the placeholder is in.
If you can't use Boost either, you need to keep in mind that the old binders need special nested types from their bound functor argument, and function pointers don't have those, which is why the ptr_fun
helper exists:
std::transform(vec.begin(), vec.end(), vec.begin(),
std::bind1st(std::ptr_fun(&std::max<int>), 5));
Upvotes: 0
Reputation: 1759
You can use std::replace_if instead of transform. This allows you to use a predefined comparsion functor like std::less
or std::greater
instead of std::max
:
std::replace_if(vec.begin(),vec.end(),std::bind2nd(std::less<int>(),5),5);
Here is a working example.
Upvotes: 2