Function Overloading with const [duplicate] - c++

This question already has answers here:
Why is this call to member function ambiguous?
(3 answers)
Closed 5 years ago.
struct A
{
void fn(double a) const {}
void fn(int a){}
};
int main()
{
A().fn(1.);
}
For the above mentioned function why does the compiler produce an ambiguity; Both the types are different.

Why would you like to pass an int only to a non-const A?
There are two parameters to each member function, this and a. So you require a const A* for this and doublefor a, or non-const A* and int.
And the call doesn't fully match either alternative, as you have non-const Aand double. So the compiler can either convert A() to const A, or doubleto int. And it cannot decide which is the best.

Related

Interpretation of access decoration of member functions [duplicate]

This question already has answers here:
What does the single ampersand after the parameter list of a member function declaration mean?
(3 answers)
Const reference qualifier on a member function [duplicate]
(2 answers)
What is "rvalue reference for *this"?
(3 answers)
Closed 8 months ago.
In C++11 and later, one can decorate the member function with &, const&, oe && (or other combinations).
If one has several overloads, and at least one is specified like this, the others must follow the same convention.
Pre C++11 style:
struct A {
void f() const {} // #1
void f() {} // #2
};
C++11 and later:
struct {
void f() const& {} // #3
void f() & {} // #4
// void f() && {} // if necessary
};
Until today, I though that #4 was equivalent to #2, but today I found a counter example:
struct A {
void f() & {}
// void f() && {} // commented for testing purposes, see below
}
struct B {
void f() {}
}
...
A{}.f(); // compile error: argument discards qualifiers
B{}.f(); // ok
https://godbolt.org/z/qTv6hMs6e
So, what is the deal? An undecorated (non-const) member function written in the old style is equivalent to both its && or & version depending on the context (at the calling point)?
Is the below code the correct interpretation?
struct B {
void f() {... some body...}
}
...is the same as this?
struct B {
void f() & {... some body...}
void f() && {... some (same) body...}
}
... which is the same as this:
struct B {
void f() & {... some body...}
void f() && {return f();}
}
The qualifiers have the exact same meaning as if they were the qualifiers on the hypothetical implicit object parameter which is passed the object expression of the member access expression.
So, #4 can not be called on a prvalue, because a non-const lvalue reference can not bind to a prvalue, explaining why A{}.f(); doesn't work. (A{} is a prvalue)
The old style without reference qualifier is the odd one. It behaves in overload resolution as if the implicit object parameter was an lvalue reference (const or not depending on that qualifier), but in contrast to normal function parameters it is allowed to bind to rvalues anyway for the purpose of overload resolution.
So to replicate the old style unqualified behavior, you need to specify both the &-qualified overload and the &&-qualified overload (at least if the function is not also const-qualified). (There are likely some corner cases where the two qualified member functions are not 100% equivalent to one unqualified one though. I guess a simple example would be trying to take the address &B::f.)

Using member function without taking address? [duplicate]

This question already has answers here:
Pointer to member function - syntax
(2 answers)
Closed last year.
class C{
public:
int i(){return 3;}
};
void memfn(int (C::* const & func)()){}
void fn(int (* const & func)()){}
int main() {
fn(&foo); //Works
fn(foo); //Works
memfn(&C::i); //Works
memfn(C::i); //Doesn't Work
}
When passing a function pointer as a parameter, the address-of operator is optional on the function. Why does it not work if removed on a member function?
There is an implicit conversion from global function references, or static member function references, or non-capturing lambdas, to function pointers. This is for capability with C.
But such implicit reference-to-pointer conversions are not for non-static member functions (and capturing lambdas!), because they need an implicitly passed this pointer to work, the conversion just lacks that thing.
In your case, if we make i() static, then it can be passed to fn either by reference or by address.

What's the difference between const member function and const-ref member function [duplicate]

This question already has an answer here:
c++ - const member func, that can be called upon lvalue instances only, using a ref-qualifier
(1 answer)
Closed 2 years ago.
For the following code:
class C
{
public:
void fun() const {};
void fun() const & {};
};
I know that this is illegal, since we cannot overload with const and const &. However, my question is: we already have const member function in the old standard, why did we need to introduce the const & member function? Are there any semantic differences between a const member function and a const-ref member function?
What's the difference between const member function and const-ref member function
Lvalue ref qualified function cannot be called on rvalue instance arguments (unless the function is also const qualified). Unqualified member functions can be.

C++ access rvalue referenced object from non rvalue object [duplicate]

This question already has answers here:
My attempt at value initialization is interpreted as a function declaration, and why doesn't A a(()); solve it?
(5 answers)
Closed 8 years ago.
This question may be sound stupid. I just want to make sure. And maybe that someone point me where this described in standard.
We cannot have rvalue referenced objects inside lvalue. Right?
struct A{int value;};
struct B{
B(A &&value) : a(std::forward<A>(value)){}
A&& a;
};
int main()
{
// allowed
B(A()).a;
// error
B b(A());
b.a;
return 0;
}
http://coliru.stacked-crooked.com/a/ea6bd617d421a8b8
B b(A()); declares a function (most vexing parse). You get a compiler error because b has no member a.
To fix the issue write B b{A()} instead.

A quick c++ query [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Overloading by return type
Why can't I declare three member functions like this:
void x(int a);
void x(String a);
int x(String a);
?
Because you can't overload by return type.
void x(string a)
and
int x(string a)
have the same signature. The signature is made of:
function name
parameters
cv-qualifiers
Which, in your case, are the same.
C++ does not allow you to overload functions based on the return type. Function overloading is only allowed based on the type of the arguments. This means that void x(String a) and int x(String a) are seen as the same function as far as overloading rules are concerned.
One important case that may be confusing (but is often used) is when const is put at the end of a member function. That would look something like int number_of_peanuts(bool tasty_only) const. That const at the end means that the class that this member function is part of cannot be modified by this function.
However, this is actually just a special case of argument type overloading. When you have a member function that is not declared static, there is implicitly an extra parameter added to your function, this this pointer. This means that the example function I gave is roughly equivalent to int number_of_peanuts(Class const * this, bool tasty_only). If you didn't have const at the end of the function, then instead it would be like int number_of_peanuts(Class * this, bool tasty_only).
So to summarize, the type and number of arguments are the only thing that allow you to overload. If you pass by value, as in void x(int a), then const won't give you overload opportunities, because the outside world cannot tell the difference between whether you modify your copy or not. If you pass by reference or pass a pointer, then you can use const with the thing they are referring to as overload options, so void x(std::string & a) and void x(std::string const & a) are different, because the world can tell if you modify a or not. Putting const at the end of the function is another source of overload opportunity. And finally, and most obviously, void x(int a) and void x(int a, int b) is a legal overload because you have a different number of arguments.