Is () used in the bool operator()(int num) of the below code a another operator or it means something else ? Please help.
#include <iostream>
#include <vector>
#include<algorithm>
using namespace std;
class IsOdd{
public:
bool operator()(int num){
return ((num%2)==1);
}
};
int main(){
vector <int> v {1,2,3,4,5,6,7,8,9,10};
vector <int>::iterator pend;
vector<int>:: iterator q;
pend = remove_if(v.begin(), v.end(), IsOdd());
for(q=v.begin(); q!=pend;++q)
cout<<*q<<endl;
return 0;
}
That means overloading the operator () to work with the IsOdd class.
Here is a sample of code of the overloaded operator in action:
#include <iostream>
#include <vector>
#include<algorithm>
class IsOdd {
public:
bool operator()(int num) {
return ((num % 2) == 1);
}
};
int main()
{
std::vector <int> v{ 1,2,3,4,5,6,7,8,9,10 };
IsOdd isOdd; // Defining object isOdd of the class IsOdd
for (int i = 0; i < v.size(); i++)
{
if (isOdd(v[i])) std::cout << v[i] << " is odd." << std::endl;
else std::cout << v[i] << " is not odd." << std::endl;
}
return 0;
}
I've also removed the iterators and shown with a much simpler way to iterate through elements in a std::vector.
Also, you should not use the following in your code:
using namespace std;
...as it's considered as bad practice.
Output:
1 is odd.
2 is not odd.
3 is odd.
4 is not odd.
5 is odd.
6 is not odd.
7 is odd.
8 is not odd.
9 is odd.
10 is not odd.
It's a function, and the () is part of the name - operator() is a special spelling for "function that is used to make an object behave like a function".
(It's a bit strange to call it "operator", but the C++ committee prefers reusing keywords to introducing new ones.)
If you have an object of the IsOdd type, such as
IsOdd is_odd;
then what looks like a regular function call,
is_odd(3)
is transformed behind the scenes into
is_odd.operator() (3)
IsOdd is a functor class. It has an overload of the function call operator, so that given an instance x you can call it via x(42) to determine if 42 is odd.
In the code it is used to pass a callable to the algorithm. Nowadays you would rather use a lambda:
auto isOdd = [](int x) { return ((num % 2) == 1);};
pend = remove_if(v.begin(), v.end(), isOdd);
or perhaps, if the functor is only needed for the algorithm but not elsewhere, define the lambda in-line:
pend = remove_if(v.begin(), v.end(), [](int x){ return ((num % 2) == 1);});
Is () used in the bool operator()(int num) of the below code a another operator or it means something else ?
Here:
pend = remove_if(v.begin(), v.end(), IsOdd());
the () in IsOdd() is a call to the constructor to create an instance of the class IsOdd. The operator() of that instance is then called by the algorithm. If you like you could also call it yourself:
auto x = IsOdd(); // call constructor
std::cout << x(42); // call operator()
It means it's a function named operator(), returns a boolean, and takes in an integer named num.
Edit:
Its an overloaded function operator so you can have it take no arguments or the argument int num.
Related
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template <class T>
class Sum {
public:
Sum(T i = 0) : res(i) {}
void operator()(T x) { res =res + x; }
T result() const { return res; }
private:
T res;
};
int main() {
Sum<int> s;
vector<int> vec;
vec.insert(vec.begin(), 10);
vec.insert(vec.begin()+1, 10);
vec.insert(vec.begin()+2, 10);
vector<int>::iterator itr = vec.begin();
cout << *itr << endl;
for_each(vec.begin(), vec.end(), s);
cout << "sum is" << s.result() << endl;
return 0;
}
This is my code. I want to add vec values in class Sum res. for_each should be calling s's operator(), so the result should be 30, but it shows 0.
I think adding value in vector has no problem. Why is the s.operator() is not working?
for_each takes its third argument by value which means every invocation of operator() affects a completely separate copy of s. There's an algorithm for exactly what you're doing called std::accumulate, but if you want this to work with for_each you need to pass s "by reference" by using std::ref from <functional>.
for_each(vec.begin(), vec.end(), ref(s));
for_each returns a copy of the passed-in functor that provides the "result" of the iteration (whatever the result is). Change your call to:
auto s = for_each(vec.begin(), vec.end(), Sum<int>());
I am learning functors and their usages. I came across below code in one of stack overflow questions.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class CalculateAverage
{
private:
std::size_t num;
double sum;
public:
CalculateAverage() : num (0) , sum (0)
{
}
void operator()(int elem)
{
num++;
sum += elem;
}
operator double () const
{
return sum / num;
}
};
int main()
{
vector<int> values;
for (int i = 1; i <= 5; i++)
values.push_back(i);
int average = std::for_each(values.begin(), values.end(), CalculateAverage());
cout << average << endl;
}
Output : 3
I understood functor concept. But I didn't understand why conversion function is getting called. std::for_each() returns the same function that we pass to for_each() as the last argument. Here we are passing () overloaded function. Can some one please help me to understand why conversion function is getting called in this case?
You are not passing a function to std::for_each, you are passing a functor (an object that acts like a function). When std::for_each returns it returns the function object you passed it. Your function object is of type CalculateAverage but you are trying to assign it to an int. So the conversion operator is chosen to convert the returned CalculateAverage into a double and then that is used to initialize average.
could you tell me why this code works? There is overloaded operator() which is used by replace_if algorithm. In main function I've created constant object of IsEqual class so only constant function member should be used. Somehow constancy isn't working and that operator is called.
#include <iostream>
#include <vector>
#include <algorithm>
class IsEqual {
int value;
public:
IsEqual(int v) : value(v) {}
bool operator()(const int &elem){
this->value=6;
return elem == value;
}
};
int main()
{
const IsEqual tst(2);
std::vector<int> vec = {3,2,1,4,3,7,8,6};
std::replace_if(vec.begin(), vec.end(), tst, 5);
for (int i : vec) std::cout << i << " ";
std::cout<<std::endl;
}
result: 3 2 1 4 3 7 8 5
std::replace_if will make its own copy of the tst object. It is not required to restrict it to be const.
If you want to use the original object in the algorithm, you can use an std::reference_wrapper. Since it would be referring to a const object,this would result in a compiler error because it would require the operator to be const:
std::replace_if(vec.begin(), vec.end(), std::ref(tst), 5);
I'm writing a simple test to see how C++11 Lambdas can be used for the purpose of maximizing code reuse. I have a function, fill_vector() and in one case I'd like it to simply fill a vector with random numbers, but in another case I'd like it to also provide me with the maximum of those numbers.
Here's what I have so far:
#include <iostream>
#include <random>
#include <vector>
#include <algorithm>
#include <iterator>
template <class Function>
void fill_vector(std::vector<int> &v, Function side)
{
for(auto i=v.begin(); i!=v.end(); ++i)
{
*i = rand() % 100;
}
side.lambda(v);
}
class null_test
{
public:
constexpr static auto lambda = [] (std::vector<int> x) { };
};
class test
{
public:
test() : max(0) { }
int max;
static auto lambda = [=] (std::vector<int> x) { max =
std::max_element(x.begin(),x.end()); };
};
int main()
{
std::vector<int> v(20);
null_test n;
fill_vector(v,n);
std::copy(v.begin(),v.end(),std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
std::vector<int> v2(20);
test t;
fill_vector(v2,t);
std::copy(v.begin(),v.end(),std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
std::cout << t.max << std::endl;
return 0;
}
Which results in the error: ‘this’ was not captured for this lambda function, pointing at my lambda defined in test. I've tried all sorts of capture statements and can't seem to get anything to work. What am I missing?
Also, is it possible to use a lambda inside the loop of fill_vector that could, say, extract every nth element filled? My goal here is to be able to reuse a function like fill_vector as much as possible for other functions that might need slight variations of it in a bigger project.
Looking at your class test:
class test
{
public:
int max;
static auto lambda = [=] (std::vector<int> x) {
max = std::max_element(x.begin(),x.end());
};
};
There are several problems here:
operator() on a lambda is const, and you are trying to modify a member.
You are trying to assign the value to an external variable, but are capturing it by-value, so even if you made the lambda mutable, nothing would happen.
You are trying to assign a member of a class using a static function that does not take an instance of that class.
As dyp points out, std::max_element returns an iterator, not the actual element.
The lambda you want to write probably looks like this:
test t;
std::vector<int> v2(20);
fill_vector(v2, [&t](const std::vector<int>& x){
t.max = *std::max_element(x.begin(), x.end());
});
Just change your fill_vector() function to take a callable, rather than something that has a callable.
I was just reading this
class biggerThan
{
public:
const int testValue;
biggerThan(int x) : testValue(x) { }
bool operator()(int val) const
{ return val > testValue; }
};
Now say its used like
std::list<int>::iterator firstBig =
std::find_if(aList.begin(), aList.end(), biggerThan(12));
OR
Just simply like this
biggerThan object(12)
Now when biggerThan(12) this is used it can invoke the constrcutor to initialze the testvalue or () operator is overloaded and 12 is passed to the function(bool operator()(int val) const ) so that it returns a bool.
which one happens first/how does it works
does it leads to any ambiguity or does the call to the overlaode operator happens in some fashion like
object.operator().(12).
please make my undersatnding clear.
Maybe the following code will make it clear:
#include <iostream>
#include <algorithm>
class biggerThan
{
public:
const int testValue;
biggerThan(int x) : testValue(x) {
std::cout << "Construction of biggerThan object with value "
<< x << std::endl;
}
bool operator()(int val) const
{
if (val > testValue) {
std::cout << val << " is bigger than " << testValue
<< std::endl;
return true;
}
else {
std::cout << val << " is *not* bigger than " << testValue
<< std::endl;
return false;
}
}
};
int main() {
int data[] = {0,1,2,3,4,5,6,7,8,9};
std::for_each(data, data+10, biggerThan(4));
}
The output is:
Construction of biggerThan object with value 4
0 is *not* bigger than 4
1 is *not* bigger than 4
2 is *not* bigger than 4
3 is *not* bigger than 4
4 is *not* bigger than 4
5 is bigger than 4
6 is bigger than 4
7 is bigger than 4
8 is bigger than 4
9 is bigger than 4
What happens:
The last argument to std::for_each is an object of type biggerThan, that is constructed with the argument 4.
The operator()(int) of this biggerThan-object (actually a copy of it) is invoked for every element in data.
The algorithm you use (std::find_if) works the same in this regard.
when biggerThan(12) this is used it can invoke the constructor to initialize the testvalue
Yes. biggerThan(12) creates an instance of the biggerThan class with testvalue set to 12.
When std::find_if() calls the functor, it will call the operator()(int val) member function of that instance.
biggerThan(12) will pass an object of biggerThan at std::find_if(aList.begin(), aList.end(), biggerThan(12)); line;
To invoke operator() following is the way;
biggerThan obj(12); //This is a constructor call
biggerThan(13); //This is function operator call
#std::find_if(aList.begin(), aList.end(), biggerThan(12)); the third parameter that is passed will be temporary object of biggerThan initialized with 12
In general, you can accomplish the same thing using greater<> and bind2nd<>, which are in <functional>
list<int>::iterator firstBig = find_if(aList.begin(), aList.end,
bind2nd(greater<int>(), 12));
bind2nd turns any binary function object, like greater<int> into a unary function object. In the case of greater<int> it effectively creates a function object whose less than operator looks like this
bool operator>(const int& arg)
{
return functor.operator>(arg, 12);
}
where functor is greater<int>