using operator & after class method name [duplicate] - c++

This question already has answers here:
const& , & and && specifiers for member functions in C++
(2 answers)
Closed 4 years ago.
I found the C++ class with API like this:
class foo
{
.....
public:
int& func1() & ;
int func1() && ;
.....
}
what does operator & and && do after the method name and what is the difference between these two function.

These are called "ref qualifiers" and allow you to overload a member function depending on the value category of *this.
int& func1() & means: this overload of func1 can be invoked on any instance of *this which can be bound to an lvalue reference.
int func1() && means: this overload of func1 can be invoked on any instance of *this which can be bound to an rvalue reference.
E.g.
foo f; f.func1(); // calls &-qualified version
foo{}.func1(); // calls &&-qualified version

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.

How to resolve ambiguous function selection in C++? [duplicate]

This question already has answers here:
Overload resolution between object, rvalue reference, const reference
(1 answer)
C++ function overloading resolution involving pass-by-value, reference and constant reference
(3 answers)
Function Overloading Based on Value vs. Const Reference
(6 answers)
Closed 2 years ago.
How could i select the overloaded function that i mean to call ?
Consider this code:
void foo (std::vector<int> const &variable);
void foo (std::vector<int> variable);
For example in above code i want to call void foo (std::vector<int>);, I tried :
void bar ()
{
std::vector<int> tmp;
foo(tmp);
foo(static_cast<std::vector<int>(tmp));
foo(boost::implicit_cast<std::vector<int>>(tmp));
foo((std::vector<int>)tmp);
foo(std::vector<int>(tmp));
}
But it's failed, How could i do that without changing the functions signature ?

How to route to different implementations according to whether an object is a rvalue reference or not? [duplicate]

This question already has an answer here:
What is the purpose of Ref-qualified member functions ? [duplicate]
(1 answer)
Closed 3 years ago.
For example, I have a class called MyClass and create an instance from it:
auto obj = MyClass()
I have two ways to call its method.
Option 1: call the method directly
obj.method()
Option 2: cast obj to rvalue reference first, then call the method
std::move(obj).method()
I was wondering whether it is possible to create different implementation of method between Option 1 and Option 2. Is there a way to route/overload the method according to whether an object is a rvalue reference or not?
You can declare member functions with reference qualifiers. e.g.
class MyClass {
public:
void method() & { std::cout << "on lvalue\n"; }
void method() && { std::cout << "on rvalue\n"; }
};
then
auto obj = MyClass();
obj.method(); // invoke the lvalue version
std::move(obj).method(); // invode the rvalue version
Is there a way to route/overload the method according to whether an object is a rvalue reference or not?
To be precise, which overloading is selected in overload resolution depends on whether the object to be called on is an lvalue or rvalue, not its type is rvalue reference or not. Types and value categories are two independent things.