Could you explain me how these functions work?
double f(int i)
{
cout<<"a";
return 1;
}
int f(double i)
{
cout<<"b";
return 1;
}
For:
f(f(f(1)));
In my opinion the result should be: aaa
but it isaba
And same situation with f(f(f(1.1)));
I think there should be aab but there is bab
When you return from a function, the type of the return value is determined from the function prototype, not what it's written as-is. If the type doesn't match, it'll be implicitly converted to the correct type. So this example function:
double foo(void) { return 1; }
Actually returns double(1), or equivalently, 1.0. It does not return an int because 1 is int. It does, however, convert your int to a double value to match the function's return value type as declared.
So coming to your question, the innermost function called is double f(int), and the second function called is int f(double), and the outermost function called is double f(int). This matched the output you see: aba.
f( f( f(1) ) );
↑ ↑ ↑
| | calls double f(int)
| calls int f(double)
calls double f(int)
The way the compiler reads your f(f(f(1))); function is from the inside out. Let me elaborate, the compiler sees f(1); and it looks for a function called f that takes an int as an argument so that would be:
double f(int i)
{
cout<<"a";
return 1;
}
Now, once your function executes, it returns a double, hence the second f takes in a double -> which calls your next function that takes double
int f(double i)
{
cout<<"b";
return 1;
}
Following the logic explained above, we have arrived at the last/outer layer of your triple f question. Now the compiler has an int and is looking for a function called f that takes int -> which is your first declared function.
And that is why you get aba as a result.
prior to your first use of std::cout in your code, add the line
std::cout << std::fixed;
This changes the output (of parameter i) quite a bit by causing int and double to show their 'true colors'. Perhaps this will illustrates what is happening.
Example:
double f(int i)
{
std::cout << " a" << std::setw(9) << i << " " << std::flush;
return 1;
}
int f(double i)
{
std::cout << " b" << std::setw(9) << i << " " << std::flush;
return 1;
}
int main(int , char** )
{
std::cout << std::fixed << "\n";
f(f(f(1)));
std::cout << std::endl;
f(f(f(1.0)));
return 0;
}
Generates output:
a 1 b 1.000000 a 1
b 1.000000 a 1 b 1.000000
The returned value (always integer 1) is implicitly transformed to the return type, which is different for the two functions.
Which function is invoked is determined by the signature of the function, i.e. the parameters actual type. This also illustrates that the return type is not part of the signature.
Related
I have the following:
void print_str(std::shared_ptr<std::string> str) {
std::cout << str->c_str() << std::endl;
}
int main() {
auto str = std::make_shared<std::string>("Hello");
std::function<void()> f = std::bind(print_str, str);
f(); // correctly print: Hello
return 0;
}
I think the type of std::bind(print_str, str) is std::function<void(std::shared_ptr<std::string>)>, but the code above is correctly running. Is there any trick in std::bind?
env: centos, gcc82
What std::bind does is correct. It uses the value you provided (str) for the call to print_str. So you don't need to specify it anymore and will always be replaced by the bound value.
#include <iostream>
#include <functional>
int sum(int value1, int value2) {
return value1 + value2;
}
int main() {
std::function<int(int, int)> f1 = std::bind(sum, std::placeholders::_1, std::placeholders::_1);
std::function<int(int)> f2 = std::bind(sum, 10, std::placeholders::_1);
std::function<int()> f3 = std::bind(sum, 100, 200);
std::function<int(int)> f4 = std::bind(sum, std::placeholders::_1, 200);
int a = 1;
int b = 2;
std::cout << "the sum of " << a << " and " << b << " is: " << f1(a, b) << std::endl;
std::cout << "the sum of " << 10 << " and " << b << " is: " << f2(b) << std::endl;
std::cout << "the sum of " << 100 << " and " << 200 << " is: " << f3() << std::endl;
std::cout << "the sum of " << 200 << " and " << b << " is: " << f4(b) << std::endl;
return 0;
}
output:
the sum of 1 and 2 is: 2
the sum of 10 and 2 is: 12
the sum of 100 and 200 is: 300
the sum of 200 and 2 is: 202
f1 binds no values but placeholders and returns an int(int, int) like function
f2 binds one value and one placeholder and returns an int(int) like function
f3 binds two values and no placeholder and returns an int() like function
f4 is like f2 except that the place holder is now the first parameter instead of the second one.
Your code falls into the f3 case.
I think the type of std::bind(print_str, str) is std::function<void(std::shared_ptr<std::string>)>
No, the type of std::bind(print_str, str) is an unspecified functor type, something like
class binder
{
void(*f)(std::shared_ptr<std::string>);
std::shared_ptr<std::string> p;
public:
template<typename... Args>
void operator()(Args... ) { f(p); }
};
Note that this is callable with any arguments or none.
What you are experiencing here is correct and is precisely doing what std::bind was designed for.
Simply speaking:
It turns a function taking n parameters into a function taking m parameters (where n >= m).
In your particular case, you give it a function taking one parameter and get back a function taking zero parameters. This new function will internally call print_str and always pass str as argument.
Side note:
Since there are lambdas in C++11, std::bind is sort of redundant.
What you are doing is exactly equivalent to this:
void print_str(std::shared_ptr<std::string> str) {
std::cout << str->c_str() << std::endl;
}
int main() {
auto str = std::make_shared<std::string>("Hello");
std::function<void()> f = [=]() { print_str(str); };
f(); // correctly print: Hello
return 0;
}
This hopefully also helps understanding what std::bind does behind the scenes.
Consider the following code and output:
#include <iostream>
int Add(int a, int b) {
return a + b;
}
int Subtract(int a, int b) {
return a - b;
}
int main() {
int (*fn1)(int, int);
int (*fn2)(int, int);
fn1 = &Add;
fn2 = &Subtract;
std::cout << "fn1 = " << fn1 << "\n";
std::cout << "*fn1 = " << *fn1 << "\n";
std::cout << "fn2 = " << fn2 << "\n";
std::cout << "*fn2 = " << *fn2 << "\n";
}
Output:
fn1 = 1
*fn1 = 1
fn2 = 1
*fn2 = 1
As a pointer, I would expect fn1 and fn2 to be memory addresses, and I don't really know what to expect for *fn1 and *fn2. According to Wikipedia, "a function pointer points to executable code within memory", but I don't see how "executable code within memory" corresponds with "1".
*fn1 is a function lvalue, and such a value decays to a pointer to that function in most circumstances, including when passed as a function call argument.
You can dereference the result of the decay to get another function lvalue, ad infinitum: *****fn1, ***********fn1, etc.
What are Function Pointers Ponting To?
It depends on what kind of function pointer it is. For non-member function pointer (as in your example), the pointer usually points to the actual code for the function (though on some architectures, such as PowerPC, it may point into a special "function descriptor" instead):
To examine that value, you should print it as void *, and not as bool (which is what you have done in your example).
std::cout << "fn1 = " << (void*)fn1 << std::endl;
Another way to examine it is using a debugger. For example, in GDB:
(gdb) p/a fn1
(gdb) p/a fn2
This question already has an answer here:
Using float gives "call to overloaded function is ambiguous" error [duplicate]
(1 answer)
Closed 6 years ago.
I'm learning C++ through Sololearn. I have a doubt about function overloading
this is the code
#include<iostream>
using namespace std;
void printSomething(int x) {
cout << "I'm printing an integer " << x << endl;
}
void printSomething(float x) {
cout << "I'm printing a float " << x << endl;
}
int main() {
int a =3;
float b = 2.65;
printSomething(a);
printSomething(b);
return 0;
}
it gives output as
I'm printing an integer 3
I'm printing a float 2.65
but if I directly give argument when calling function
like this
#include<iostream>
using namespace std;
void printSomething(int x) {
cout << "I'm printing an integer " << x << endl;
}
void printSomething(float x) {
cout << "I'm printing a float " << x << endl;
}
int main() {
printSomething(3);
printSomething(2.65);
return 0;
}
i get following error
..\Playground: In function 'int main()':
..\Playground:19:24: error: call of overloaded 'printSomething(double)' is ambiguous
printSomething(2.65);
^
..\Playground:19:24: note: candidates are:
..\Playground:5:6: note: void printSomething(int)
void printSomething(int x) {
^
..\Playground:9:6: note: void printSomething(float)
void printSomething(float x) {
^
but if I change
void printSomething(float x) {
cout << "I'm printing a float " << x << endl;
}
to
void printSomething(double x) {
cout << "I'm printing a float " << x << endl;
}
I will get output as
I'm printing a float 2.65
why is it?
but if it's only the integer it works fine
#include<iostream>
using namespace std;
void printSomething(int x) {
cout << "I'm printing an integer " << x << endl;
}
void printSomething(float x) {
cout << "I'm printing a float " << x << endl;
}
int main() {
printSomething(3);
return 0;
}
Result
I'm printing an integer 3
Why isn't this working with float
Thankyou
2.65 is not a float literal, it's a double literal.
So the compiler doesn't know whether you want to convert the double to a float or an int and so issues the error.
In your first case, when writing float b = 2.65; the compiler assumes you know what you're doing, and calling the overload with b is unambiguous.
If you had written printSomething(2.65f); then that would also have been unambiguous: 2.65f is a float literal.
2.65 is considered a double. But you didn't provide an overload void printSomething(double x). Therefore the compiler must cast the value and it doesn't know if it should cast to float or int (both with precision loss`).
If you write 2.65f it is considered a float and it should work.
The reason for that is the conversion rules and overload resolution strategy. If C++ is unable to find an exact match on parameters, it looks for a conversion. The best conversion is an implicit one, that is widening (casting a data type to one that can hold all the values of the original type and potentially more), then a narrowing conversion (casting to a smaller data type, which may cause errors or loss of precision for some values), then a user-defined conversion.
As literal 2.65 is of type double, the compiler looks for conversions. There are two: double -> float and double -> int. They are both narrowing, which means they are equally good. The compiler is unable to pick the best one, thus reports an error.
To remedy this, you can either:
define overload for double as you did
use a float literal (2.65f) instead of a double
using namespace std;
double func(double a, double b)
{
return a - b;
}
int main()
{
double result = (boost::bind(&func, _1, _2))(1,0, 2.0);
cout << "a: " << result << endl;
result = (boost::bind(&func, _2, _1))(1,0, 2.0);
cout << "b: " << result << endl;
return 0;
}
Output:
a: 1
b: -1
I think it is the simplest boost::bind example.
But it acts weird not as I expect.
I'm using boost_1.58_0, gcc 4.8.4.
Could anybody tell me why those place holders are switched ??
You have a typo and are passing three arguments to the bound functor:
(1,0, 2.0);
This substitutes 1 for the _1 placeholder, and 0 for the _2 placeholder, and ignores the third argument, so func runs 1 - 0 which is 1.
For the second call you pass the same arguments, but they are passed to the wrapper functor in a different order so func runs 0 - 1 which is -1.
I have this following code that I must follow:
#include <iostream>
using namespace std;
class T {
public:
T() {}
};
class S {
public:
static int i;
S() { i++; }
S(int unused) { i += 2; }
S(T unused) { i += 3; }
};
int S::i = 0;
S f(S unused)
{
return 0;
}
S g(S& unused)
{
return 1;
}
int main()
{
cout << S::i << "\n";
S s1, s2(2);
cout << S::i << "\n";
T t;
cout << S::i << "\n";
S s3(t);
cout << S::i << "\n";
f(t);
cout << S::i << "\n";
g(s1);
cout << S::i << "\n";
}
From following every declaration and instantiation in the main method, I can follow the output as follows:
0
3
3
6
6
6
I am correct until:
0
3
3
6
But the last two numbers that will be outputted are:
11
13
I am unsure what exactly f(t) and g(s1) do? I am unable to follow how they are changing the value of i.
What do these two statements do?
Both f() and g() are declared to return a value of type S but they actually do a return with an integer value.
So what actually happens is that a temporary value of type S is automatically created from the integer using the conversion constructor S(int unused). That function increments S::i by 2.
Also f() takes as argument a value of type S, but it is calld with a value of type T. Hence, a temporary value of type S is automatically created by the compiler, using the conversion constructor S(T unused). That function increments S::i by 3.