Function Overloading C++ Pointers - c++

I understand that the overloading a function is legal if the number of parameters are different, or if the parameter type is different.
Why is it that a difference of only the return type is not legal?
Also, is it legal to overload as such:
int hello(int x);
int hello(int &z);
also
int hi(int x);
int hi(int *z);

There's no way for the compiler to figure out which function you're trying to call by just the return value. Since a return value does not need to be caught, you could write:
hello( 1 ); // return int
hello( 2 ); // return float
They are exactly the same call from what can be seen.
Yes that is legal since the first hi takes a reference and the second hi takes a memory address. You might call it like this:
hi( myNumber );
hi( &myNumber );
Perfectly distinguishable.

It's hard for compiler to choose an overload based on the return type. In many situations there is no explicit statement for compiler to deduce the programmer's purposed return type. Even if it was possible, it's confusing for programmers.
Assume C++ has overloading based on return values:
float func() {...};
int func() {...};
int x = func(); // OK, compiler may choose `int` version!
BUT, How about...
cout << func() + func();
What do you expect? Maybe we can define some rules, but it will make codes complex, confusing and unreadable.
Other overloadings are legal. Due to different entry argument types.

You can't overload:
int hello(int x) // 1
{
return x;
}
int hello(int& x) // 2
{
return x;
}
int hello(int const& x) // 3
{
return x;
}
void foo()
{
int i = 10;
hello(i); // Can't disambiguate between 1 and 2
hello(10); // Can't disambiguate between 1 and 3
}
However, you can overload:
int hello(int& x) // 4
{
return x;
}
int hello(int const& x) // 5
{
return x;
}
void foo()
{
int i = 10;
hello(i); // Picks 4
hello(10); // Picks 5
}

Think about how the compiler might be able to figure out what function you want to be called. In the first example, if I write
int z = 5;
int y = hello (z);
How is the compiler going to figure out which function you want to be called? But in the second example,
int z = 5;
int y = hi (z);
int u = hi (&z);
it's clear which function to call. You can't overload on return type alone because the compiler needs the parameters to choose the function to call.

For me it's good, this is not the same type; for exemple int x is an integer, but int *z is un pointer of integer.

There are really no technical problems with allowing overloading on return type in many cases, the compiler knows what type is needed for the expression the function call is in and so knows which function to call. There are some problems though, for example if the returned value is not used, then you will have an ambiguity.
As for the functions, all of those are valid overloads. You might have some ambiguity in the case of hello depending on how you call it, for example if you call it with a variable then the compiler can't really tell which version of hello you want.

Since int, int& and int* are all different types then overloading on these is legal.
You can also overload on const which can be useful when designing classes which exhibit true const correctness.
int hello(int);
int hello(int) const;
You cannot overload on return types since the compiler would not know which function to use in full generality, especially if the function return type is discarded by the caller.

Related

Why is the constructor not called when assigning a functor to a std::function? [duplicate]

For example a declaration such as that:
int (x) = 0;
Or even that:
int (((x))) = 0;
I stumbled upon this because in my code I happened to have a fragment similar to the following one:
struct B
{
};
struct C
{
C (B *) {}
void f () {};
};
int main()
{
B *y;
C (y);
}
Obviously I wanted to construct object C which then would do something useful in its destructor. However as it happens compiler treats C (y); as a declaration of variable y with type C and thus it prints an error about y redefinition. Interesting thing is that if I write it as C (y).f () or as something like C (static_cast<B*> (y)) it will compile as intended. The best modern workaround is to use {} in constructor call, of course.
So as I figured out after that, it's possible to declare variables like int (x) = 0; or even int (((x))) = 0; but I've never seen anyone actually using declarations like this. So I'm interested -what's the purpose of such possibility because for now I see that it only creates the case similar to the notorious "most vexing parse" and doesn't add anything useful?
Grouping.
As a particular example, consider that you can declare a variable of function type such as
int f(int);
Now, how would you declare a pointer to such a thing?
int *f(int);
Nope, doesn't work! This is interpreted as a function returning int*. You need to add in the parentheses to make it parse the right way:
int (*f)(int);
The same deal with arrays:
int *x[5]; // array of five int*
int (*x)[5]; // pointer to array of five int
There's generally allowed to use parentheses in such declarations because the declaration, from the syntactical point of view looks always like this:
<front type> <specification>;
For example, in the following declaration:
int* p[2];
The "front type" is int (not int*) and the "specification" is * p[2].
The rule is that you can use any number of parentheses as needed in the "specification" part because they are sometimes inevitable to disambiguate. For example:
int* p[2]; // array of 2 pointers to int; same as int (*p[2]);
int (*p)[2]; // pointer to an array of 2 ints
The pointer to an array is a rare case, however the same situation you have with a pointer to function:
int (*func(int)); // declares a function returning int*
int (*func)(int); // declares a pointer to function returning int
This is the direct answer to your question. If your question is about the statement like C(y), then:
Put parentheses around the whole expression - (C(y)) and you'll get what you wanted
This statement does nothing but creating a temporary object, which ceases to living after this instruction ends (I hope this is what you intended to do).

How to get float value from object wrapped float in the sam way?

PI'm trying to wrap float, int, etc primitves value into my SParam class. But I have some problem with getting values from this struct. I want to use this struct as I use for example floats.
template<class T>
struct SParam
{
T value;
SParam()
{
}
operator T() const
{
return value;
}
};
SParam<float> a;
a.value = 4;
printf("%f", a); //<--this don't print a.value
The problem with using the "naked" SParam<float> a with printf (or any other function that takes a variable number of arguments, for that matter) is that the compiler does not know that you want to pass a float. That is why the type-specific conversion is not applied. If you call a function with a specific parameter type, say
void printFloat(float f) {
printf("%f", f);
}
...
SParam<float> a;
a.value = 4;
printFloat(a);
then the compiler would figure out from the signature of printFloat that your conversion to float needs to be applied, and everything would work as expected. Of course you can always apply the conversion manually:
printf("%f", (float)a);
Because you need to call a() in the printf, not a.
a is just an object of type SParam, you'll probably need to modify the operator definition to specify a return type of T as well..
for comparison try using float x = a; it should give you an error. float x = a(); should not however

function with no return type

I just have 2 quick questions, I'm hoping someone can clarify for me.
When writing a function is the input paramater list the same as the parameters?
when a function has no return type is the "return 0;" just left out of the function code?
For example if I was to write a function that used to integers in its input parameter list with no return type would this be the proper way to write it?:
int convertTemp( int a, int b) {}
int convertTemp( int a, int b) {}
should be:
void convertTemp( int a, int b) {}
if function does not return anything, int means the function's return type is int. Note that you can still have return statements in a function that with return type void.
I agree with the answer above that the return type should be changed to void,
And when asking the first question you need to distinguish between formal and actual parameters.
Formal parameters are a and b in the function definition:
void func (int a, int b) {}
whereas the actual parameters are 2 and 3 in the function call:
func (2,3)
where 2 is copied to a and 3 is copied to b.
You want to make the return type void
void convertTemp( int a, int b) {
//do stuff...
return; //optional, but a good habit to get in to
}
The input parameter list is a list of type and names of the inputs. These are passes as a list of values in the calling code.
If you have no return value, then the function is declared with a void return type, and should not have a value given in the return statement.
Use the void return type to declare a function will return nothing:
void convertTemp( int a, int b) {
}
Now, how would the function convert a Temp when it returns nothing?
It should definitely not modify some state behind the scenes (like global variables).
Returning the converted value is what I would expect.
The void return type would have to be changed to the type of the conversion result.
I would definitely investigate when faced with code like the above.

function overloading with const parameters

Function overloading can happen between two member functions which have the same number of parameters, if one of them is declared as const.
But what if one function has a const argument, another has non-const argument of same type?
Will it work for references and pointers? If C++ provides it, why does it provide? Please share the reason with me if you know.
Below is the example that helps you in understanding the above scenario.
void fun(const int i)
{
cout << "fun(const int) called ";
}
void fun(int i)
{
cout << "fun(int ) called " ;
}
int main()
{
const int i = 10;
fun(i);
return 0;
}
Output: Compiler Error: redefinition of 'void fun(int)'
void fun(char *a)
{
cout<<"non-const fun() called";
}
void fun(const char *a)
{
cout<<"const fun() called";
}
int main()
{
const char *ptr = "GeeksforGeeks";
fun(ptr);
return 0;
}
Output: const fun() called
Why is the second one allowed in C++?
The first one's parameters are top-level const. This means that the function can't change the parameter's value, however, the caller doesn't care: The callee gets a copy of the argument, so if a parameter has top-level const, it's an implementation detail. Note that the following works:
void f(int); // forward declare
void g(){ f(42); }
void f(int const i){ /*...*/ } // define above declared function
For the second set of overloads, the const isn't top-level anymore. It describes whether or not the callee can change what the pointer points at. As a caller, you do care about that. It's not just an implementation detail anymore.
First, explain why the first code is not allowed while the second one is ok.
const int and int as parameter, you pass any related type, double, int or anything else can convert to int, both const int and int can accept the pass-in value, there's no difference practically. And if the complier allow to the define both, then which one to call? You don't know, neither the complier. So the first part of code is not allowed.
When it comes to second example, reference and pointer makes a difference. Because you can't pass a const int* to initialize int * and neither can use const int to initialize int&. So if you define two functions with same return type, one is "const version" pointer or reference parameter, and the other is not, that makes a difference. Another question comes up, what if I pass a int object(or called variable, same meaning) or int * pointer, then which one is matched (when parameters are pointer or reference)? The answer is the "non-const" one. if you want to match the "const version" with non-const object or non point to const pointer, you may need const_cast which I am trying to figure out.
So back to your question:
But what if one function has a const argument, another has non-const argument of same type? Will it work for references and pointers?
Yes, it to some extent only works for reference and pointers.
And
If C++ provides it, why does it provide?
Can't tell. I don't have much experience.
For further information, read the very related part sections of C++ Primer 5th.
Links of screenshots are listed as follows:
https://imgur.com/tnqrxVY
https://imgur.com/hF1MjUH
https://imgur.com/Fg2zeEw
By the way, though I am a newbie. But what is int const i from the first answer? And I don't understand what "it's an implementation detail" exactly mean. No offense, just can't understand that part of answer. :D

In C++, what does & mean after a function's return type?

In a C++ function like this:
int& getNumber();
what does the & mean? Is it different from:
int getNumber();
It's different.
int g_test = 0;
int& getNumberReference()
{
return g_test;
}
int getNumberValue()
{
return g_test;
}
int main()
{
int& n = getNumberReference();
int m = getNumberValue();
n = 10;
cout << g_test << endl; // prints 10
g_test = 0;
m = 10;
cout << g_test << endl; // prints 0
return 0;
}
the getNumberReference() returns a reference, under the hood it's like a pointer that points to an integer variable. Any change applyed to the reference applies to the returned variable.
The getNumberReference() is also a left-value, therefore it can be used like this:
getNumberReference() = 10;
Yes, the int& version returns a reference to an int. The int version returns an int by value.
See the section on references in the C++ FAQ
Yes, it's different.
The & means you return a reference. Otherwise it will return a copy (well, sometimes the compiler optimizes it, but that's not the problem here).
An example is vector. The operator[] returns an &. This allows us to do:
my_vector[2] = 42;
That wouldn't work with a copy.
The difference is that without the & what you get back is a copy of the returned int, suitable for passing into other routines, comparing to stuff, or copying into your own variable.
With the &, what you get back is essentially the variable containing the returned integer. That means you can actually put it on the left-hand side of an assignment, like so:
getNumber() = 200;
The first version allows you to write getNumber() = 42, which is probably not what you want. Returning references is very useful when overloading operator[] for your own containers types. It enables you to write container[9] = 42.
int& getNumber(): function returns an integer by reference.
int getNumber(): function returns an integer by value.
They differ in some ways and one of the interesting differences being that the 1st type can be used on the left side of assignment which is not possible with the 2nd type.
Example:
int global = 1;
int& getNumber() {
return global; // return global by reference.
}
int main() {
cout<<"before "<<global<<endl;
getNumber() = 2; // assign 2 to the return value which is reference.
cout<<"after "<<global<<endl;
return 0;
}
Ouptput:
before 1
after 2
"&" means reference, in this case "reference to an int".
It means that it is a reference type. What's a reference?
Wikipedia:
In the C++ programming language, a reference is a simple reference datatype that is less powerful but safer than the pointer type inherited from C. The name C++ reference may cause confusion, as in computer science a reference is a general concept datatype, with pointers and C++ references being specific reference datatype implementations. The declaration of the form:
Type & Name
where is a type and is
an identifier whose type is reference
to .
Examples:
int A = 5;
int& rA = A;
extern int& rB;
int& foo ();
void bar (int& rP);
class MyClass { int& m_b; /* ... */ };
int funcX() { return 42 ; }; int (&xFunc)() = funcX;
Here, rA and rB are of type "reference
to int", foo() is a function that
returns a reference to int, bar() is a
function with a reference parameter,
which is reference to int, MyClass is
a class with a member which is
reference to int, funcX() is a
function that returns an int, xFunc()
is an alias for funcX.
Rest of the explanation is here
It's a reference
It means it's returning a reference to an int, not an int itself.
It's a reference, which is exactly like a pointer except you don't have to use a pointer-dereference operator (* or ->) with it, the pointer dereferencing is implied.
Especially note that all the lifetime concerns (such as don't return a stack variable by address) still need to be addressed just as if a pointer was used.