function objects and constructors - c++

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>

Related

In C++ why is it when I reassign a reference variable to a different reference variable it creates a copy of that variable instead?

struct configfs
{
int & foo;
configfs(int & foo_) : foo(foo_) {}
void set_foo(int & foo_)
{
foo = foo_;
}
};
int main() {
int a = 1;
configfs conf(a);
a = 3;
std::cout << conf.foo; // 3
std::cout << a; // 3
int b = 2;
conf.set_foo(b);
b = 9;
std::cout << conf.foo; // 2
std::cout << b; // 9
return 0;
}
When I initialize configfs with int a and then alter a in the main function it also alters configfs.foo . But when I reassign configfs.foo to a new reference and alter that reference in the main function, the behavior is different. Why? Is there a way so that when I run conf.set_foo(b) and then alter b in the main scope, it also alters conf.foo as well?
When you wrote:
conf.set_foo(b);
The following things happen:
Member function set_foo is called on the object conf.
Moreover, the reference parameter named foo_ is bound the the argument named b. That is, b is passed by reference.
Next, the statement foo = foo_; is encountered. This is an assigment statement and not an initialization. What this does is that it assigns the value referred to by the parameter foo_ to the object referred to by the data member foo(which is nothing but a here). You can confirm this by adding std::cout<<a; after the call to set_foo as shown below:
int b = 2;
conf.set_foo(b);
std::cout<<a<<std::endl; //prints 2
This is because operations on a reference are actually operations on the object to which the reference is bound. This means that when we assign to a reference, we are assigning to the object to which the reference
is bound. When we fetch the value of a reference, we are really fetching the value of the object to which the reference is bound.
Note: Once initialized, a reference remains bound to its initial object. There is no way to rebind a reference to refer to a different
object.
Refercences can only be "assigned" during initialization. They cannot be "retargeted" the way like pointers. After the initialization the memory the reference refers to remains fixed and any assignment using = results in the invokation of the assignment operator to the memory the reference refers to. That's the way it's specified in the C++ standard.
You could rewrite the example using a custom type with assignment operators printing the information about calls:
template<class T>
struct configfs
{
T& foo;
configfs(T& foo_) : foo(foo_) {}
void set_foo(T& foo_)
{
foo = foo_; // this uses the assignment operator assigning to the variable foo is an alias for
}
};
// Type wrapping the int and printing out the operations applied
struct TestWrapper
{
TestWrapper(int value)
: value(value)
{
std::cout << "TestWrapper::TestWrapper(" << value << ")\n";
}
TestWrapper(TestWrapper const& other)
: value(other.value)
{
std::cout << "TestWrapper::TestWrapper(TestWrapper{" << other.value << "})\n";
}
TestWrapper& operator=(TestWrapper const& other)
{
std::cout << "TestWrapper::operator=(TestWrapper{" << other.value << "})\n";
value = other.value;
return *this;
}
int value;
};
std::ostream& operator<<(std::ostream& s, TestWrapper const& val)
{
s << val.value;
return s;
}
int main() {
TestWrapper a = 1;
configfs<TestWrapper> conf(a);
a = 3;
std::cout << conf.foo << '\n'; // 3
std::cout << a << '\n'; // 3
TestWrapper b = 2;
conf.set_foo(b); // TestWrapper::operator=(TestWrapper{2})
b = 9;
std::cout << conf.foo << '\n'; // 2
std::cout << b << '\n'; // 9
return 0;
}

The size of closure (lambda function) not same as std::function or pointer

#include <iostream>
#include <functional>
std::function<int(int)> makeLambda1(int x) {
return [x] (int y) { return x * y; };
}
auto makeLambda2(int x) {
return [x] (int y) { return x * y; };
}
auto makeLambda3() {
return [] (int y) { return 10 * y; };
}
int main() {
auto lambda1 = makeLambda1(10);
auto lambda2 = makeLambda2(10);
auto lambda3 = makeLambda3();
std::cout << sizeof(lambda1) << " ";
std::cout << sizeof(lambda2) << " ";
std::cout << sizeof(lambda3) << " ";
std::cout << sizeof(int(*)(int)) << std::endl;
}
Output (https://ideone.com/ghoksF):
32 4 1 8
Why is the size of a capturing lambda 4 bytes and less than the size of the std::function (32 bytes)?
Why is the size of the not capturing lambda 1 byte and less than the size of a pointer to a function (8 bytes)?
Lambdas are just syntactic sugar for objects with an overloaded operator(). That means that
return [x] (int y) { return x * y; };
is equivalent to
class unique_unnamed_type
{
private:
const int x;
public:
unique_unnamed_type(int x) : x{x} {}
auto operator()(int y) { return x * y; } const
};
return unique_unnamed_type{x};
Just from looking, you can probably guess that sizeof(unique_unnamed_type) should equal sizeof(int), since its only member is a single int.
In the non-capturing case, the equivalent object is only slightly different.
return [] (int y) { return 10 * y; };
is equivalent to
class unique_unnamed_type
{
private:
using fp = int(*)(int);
static auto unnamed_static_function(int y) { return 10 * y; }
public:
auto operator()(int y) { return unnamed_static_function(y); } const
operator fp() { return unnamed_static_function; } const
};
return unique_unnamed_type{};
This type's size will generally be 1, like any class type with no members (objects need to have a unique address, so even "empty" objects take up one byte of storage, barring things like empty base optimization).
Notably it is smaller than a function pointer because it isn't a function pointer. It's just a class with an implicit conversion operator that returns a pointer to a static member function.
std::function is a totally different beast. It's a type-erased container for any callable type that has a compatible signature. This type-erasure has some overhead, so std::function will generally be larger than a raw function pointer or a lambda, though it could be smaller, if the lambda captures a large object. The actual callable that a std::function object refers to will be allocated dynamically, and so sizeof(std::function<int(int)>) doesn't include the size of the actual callable object.
[1] std::cout << sizeof(lambda1) << " ";
this prints the size of std::function, which is implementation defined.
[2] std::cout << sizeof(lambda2) << " ";
this prints the size of unnamed unique class type instance, which has only one data member - int. The size of such closure is 4 - sizeof(int).
[3] std::cout << sizeof(lambda3) << " ";
this prints the size of unnamed unique class type instance, which has no data members. The size of empty class cannot be empty, and it is just 1 byte. See EBO, The size of any object or member subobject (unless [[no_unique_address]] -- see below) (since C++20) is required to be at least 1 even if the type is an empty class type.

std::bind of class member function

I have this code:
#include <iostream>
#include <functional>
struct Foo
{
int get(int n) { return 5+n; }
};
int main()
{
Foo foo;
auto L = std::bind(&Foo::get, &foo, 3);
std::cout << L() << std::endl;
return 0;
}
Seems that this:
auto L = std::bind(&Foo::get, &foo, 3);
is equivalento to:
auto L = std::bind(&Foo::get, foo, 3);
Why?
std::bind() accepts its arguments by value. This means that in the first case you are passing a pointer by value, resulting in the copy of a pointer. In the second case, you are passing an object of type foo by value, resulting in a copy of an object of type Foo.
As a consequence, in the second case the evaluation of the expression L() causes the member function get() to be invoked on a copy of the original object foo, which may or may not be what you want.
This example illustrates the difference (forget the violation of the Rule of Three/Rule of Five, this is just for illustration purposes):
#include <iostream>
#include <functional>
struct Foo
{
int _x;
Foo(int x) : _x(x) { }
Foo(Foo const& f) : _x(f._x)
{
std::cout << "Foo(Foo const&)" << std::endl;
}
int get(int n) { return _x + n; }
};
int main()
{
Foo foo1(42);
std::cout << "=== FIRST CALL ===" << std::endl;
auto L1 = std::bind(&Foo::get, foo1, 3);
foo1._x = 1729;
std::cout << L1() << std::endl; // Prints 45
Foo foo2(42);
std::cout << "=== SECOND CALL ===" << std::endl;
auto L2 = std::bind(&Foo::get, &foo2, 3);
foo2._x = 1729;
std::cout << L2() << std::endl; // Prints 1732
}
Live example.
If, for any reason, you don't want to use the pointer form, you can use std::ref() to prevent a copy of the argument from being created:
auto L = std::bind(&Foo::get, std::ref(foo), 3);
They are not the same. The generic function binder std::bind copies it's arguments. In the case of std::bind(&Foo::get,&foo,3), the pointer is copied, but when you call the bound object it still applies to the original foo object. In std::bind(&Foo::get,foo,3) the object foo is copied, and the later call applies to the bound copy, not to the original object.
You can test this by using a member function that accesses internal state of the object, bind the object in both ways, change the original object and see how the results differ.

Does capture by value in a C++ lambda expression require the value to be copied with the lambda object?

Does the standard define what happens with this code?
#include <iostream>
template <typename Func>
void callfunc(Func f)
{
::std::cout << "In callfunc.\n";
f();
}
template <typename Func>
void callfuncref(Func &f)
{
::std::cout << "In callfuncref.\n";
f();
}
int main()
{
int n = 10;
// n is captured by value, and the lambda expression is mutable so
// modifications to n are allowed inside the lambda block.
auto foo = [n]() mutable -> void {
::std::cout << "Before increment n == " << n << '\n';
++n;
::std::cout << "After increment n == " << n << '\n';
};
callfunc(foo);
callfunc(foo);
callfuncref(foo);
callfunc(foo);
return 0;
}
The output of this with g++ is:
$ ./a.out
In callfunc.
Before increment n == 10
After increment n == 11
In callfunc.
Before increment n == 10
After increment n == 11
In callfuncref.
Before increment n == 10
After increment n == 11
In callfunc.
Before increment n == 11
After increment n == 12
Are all features of this output required by the standard?
In particular it appears that if a copy of the lambda object is made, all of the captured values are also copied. But if the lambda object is passed by reference none of the captured values are copied. And no copies are made of a captured value just before the function is called, so mutations to the captured value are otherwise preserved between calls.
The type of the lambda is simply a class (n3290 §5.1.2/3), with an operator() which executes the body (/5), and an implicit copy constructor (/19), and capturing a variable by copy is equivalent to copy-initialize (/21) it to a non-static data member (/14) of this class, and each use of that variable is replaced by the corresponding data member (/17). After this transformation, the lambda expression becomes only an instance of this class, and the general rules of C++ follows.
That means, your code shall work in the same way as:
int main()
{
int n = 10;
class __Foo__ // §5.1.2/3
{
int __n__; // §5.1.2/14
public:
void operator()() // §5.1.2/5
{
std::cout << "Before increment n == " << __n__ << '\n';
++ __n__; // §5.1.2/17
std::cout << "After increment n == " << __n__ << '\n';
}
__Foo__() = delete;
__Foo__(int n) : __n__(n) {}
//__Foo__(const __Foo__&) = default; // §5.1.2/19
}
foo {n}; // §5.1.2/21
callfunc(foo);
callfunc(foo);
callfuncref(foo);
callfunc(foo);
}
And it is obvious what callfuncref does here.
I find it easiest to understand this behaviour by manually expanding the lambda to a struct/class, which would be more or less something like this (as n is captured by value, capture by reference would look a bit different):
class SomeTemp {
mutable int n;
public:
SomeTemp(int n) : n(n) {}
void operator()() const
{
::std::cout << "Before increment n == " << n << '\n';
++n;
::std::cout << "After increment n == " << n << '\n';
}
} foo(n);
Your functions callfunc and callfuncref operate more or less on objects of this type. Now let us examine the calls you do:
callfunc(foo);
Here you pass by value, so foo will be copied using the default copy constructor. The operations in callfunc will only affect the internal state of the copied value, no state changed in the actual foo object.
callfunc(foo);
Same stuff
callfuncref(foo);
Ah, here we pass foo by reference, so callfuncref (which calls operator()) will update the actual foo object, not a temporary copy. This will result in n of foo being updated to 11 afterwards, this is regular pass-by-reference behaviour. Therefore, when you call this again:
callfunc(foo);
You will again operate on a copy, but a copy of foo where n is set to 11. Which shows what you expect.
The value is captured by copy unless you explicitly capture-all [&] or capture a specific variable by reference [&n]. So the whole output is Standard.

C++ bind2nd question

This was one of the questions showed up on my Final exam. I can't figure out what I'm supposed to do.
I know BindSecArg requires a () operator, but not sure what goes inside.
In this question you are required to implement something similar to std::bind2nd. For simplicity main
is written using a ”for”-loop, but it may be rewritten with ”for each” and STL containers.
class Functor1 {
public:
int operator()(const int & i, const int & j) const {
return i+j;
}
};
class Functor2 {
public:
int operator()(const int & i, const int & j) const {
return i*j;
}
};
template <typename T>
class BindSecArg
};
int main () {
Functor1 f1;
for (int i=0; i<10; ++i) std::cout << f1(i,i) << " "; //0 2 4 6 8 10
std::cout << std::endl;
Functor2 f2;
for (int i=0; i<10; ++i) std::cout << f2(i,i) << " "; //0 1 4 9 16 25
std::cout << std::endl;
BindSecArg<Functor1> b1(4); //bind second argument of Functor1 to 4
for (int i=0; i<10; ++i) std::cout << b1(i) << " "; //4 5 6 7 8 9
std::cout << std::endl;
BindSecArg<Functor2> b2(4); //bind second argument of Functor2 to 4
for (int i=0; i<10; ++i) std::cout << b2(i) << " "; //0 4 8 12 16 20
std::cout << std::endl;
}
Extra credit question: your implementation most probably doesn’t work (which is OK!) with
class Functor3 {
public:
std::string operator()(const std::string & i, const std::string & j) const {
return i+j;
}
};
how does STL solve this problem?
The operator() for BindSecArg needs to take one argument (obviously), and what it's supposed to do is call the operator() from the "bound" functor, passing it (a) the passed-in "first" argument and (b) the "bound" second argument.
So we need to construct an instance of the bound functor's class (so that we can make that call), and we need to remember the second argument. We'll take care of both of these with data members.
That looks like:
template <typename T>
class BindSecArg
T toCall;
int second;
public:
// To initialize, we default-construct the bound-functor-instance, and copy the
// constructor parameter for our bound-parameter.
BindSecArg(int second): toCall(), second(second) {}
// To call, see the above discussion.
int operator() (int first) { return toCall(first, second); }
};
The standard library (please don't say "STL") bind2nd addresses this by expecting T to be an "AdaptableBinaryFunction", i.e. to provide some typedef members identifying the parameter and result types for operator(), and then using these to inherit from a base class using those typedefs as template types, and then using typedefs provided by the base class to template its own operator() implementation. These are some of the basic techniques of "template metaprogramming", and it gets complicated fast. You should look up some separate reading resources for this.
probably there are better implementations:
template <typename T>
class BindSecArg
{
public:
BindSecArg(int value2) : m_value2(value2){ };
int operator()(int value1) { return T()(value1, m_value2);}
private:
int m_value2;
};
int the link I posted in the comment to your question you can find the stl code.
Inside goes a call to Functor.operator(), passing the value given to BindSecArg in its constructor as the second argument.