overload operator [ ] to enable element assignment - c++

I've already overloaded operator [ ] to enable element access.
definition
double Matrix::operator[ ](const & int i){
return data[i]; // data[] is a member array: thrust:: device_vector
}
usage
Matrix m = ... // initialize
std::cout << m[3] << std::endl;
But now I want to access element by index so that assign new value to it.
usage
m[3] = 0.;
I understand the return value of the operator overload function must be an lvalue. I guess I should return a reference, but not sure how this is done. Thanks!
EDIT
Now I changed my definition to double &, but it still complains:
error: initial value of reference to non-const must be an lvalue
The array refers to a thrust::device_vector, which can be assigned value by index:
Thrust::device_vector<double> M(10);
M[3] = 0.;

Just replace
double ....
with
double& .....

change your definition to
double& Matrix::operator[ ](const & int i){
return data[i]; // data[] is a member array
}

Note, you should not use reference for an integer argument. It is usually used for complex classes for avoiding the copy. I would also suggest as a side note, to use m_memberVariable unless you use pimpl. This is what you should write:
double& Matrix::operator[ ] (const int i) {
return m_data[i]; // data[] is a member array
}
Note, you will need to add the '&' marker also in the class header where the method is declared.
This is all provided you have something like this in the class header:
class Matrix
{
private:
double m_data[100];
public:
double& operator[] (const int i);
};
Here you can read further details on the subscript operator overloading. This is another url for learning more about references.
As for a bit of inline explanation why it works like that:
You are trying to use the subscript operator on the left hand for assignment, hence the return value of such an operator overload has to be an l-value as you correctly state it. This is because if you return a value instead of reference, the left hand side in the usage would simply return that value which would evaluate to x = 0 where replace x with a value like 1. That is why you will get a compiler error in such cases.

Usually you chose to have a pair of operators. One for access:
double Matrix::operator[ ] const (const & int i){
return data[i];
}
and the other for assigment:
double &Matrix::operator[ ](const & int i){
return data[i];
}
If you call [ ] operator on a const object the first operator is really called. In other cases, both in access as well as assgnement, the second one is called.
You get error:
error: initial value of reference to non-const must be an lvalue
because data is (probably) a local variable. Make it a Matrix class private data member if it's not already.

Related

Why is & needed for member function pointers, not for normal function pointers?

I understand my second statement that "why & is not needed for normal function pointers" because function name itself is address of the function.
What I do not understand is why '&' is strictly needed for member function pointers?
Examples:
Normal function pointers:
int add(int a, int b) {
return (a + b);
}
int (*fp)(int, int);
fp = add;
(*fp)(2, 3) // This would give me addition of a and b, i.e. 5
Member function pointers:
class ABC {
public:
int i;
ABC() { i = 0; }
int addOne(int j) {
return j + 1;
}
};
// Member function pointer
int (ABC::*mfp)(int);
// This is what I am talking about. '&' in below line.
mfp = &ABC::addOne;
ABC abc;
std::cout << (abc.*mfp)(2) << std::endl;
It seems to me that the address-of operator is necessary for member function pointers because the right-hand side (rhs) of the declaration is a constant rather than a variable.
We wouldn't say
int (ABC::*mfp)(int);
mfp = ABC::addOne();
because that would be to invoke a function.
Furthermore, the scope resolution operator :: has the highest precedence in the C++ table of operator precedence:
https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/cpp-built-in-operators-precedence-and-associativity.md
The :: operator is evaluated before any other operators are on the rhs. I suppose the complier wonders "Hmmmm...what's that? That should be a function, but..." and then sees the address-of operator and knows what the developer needs.

c++ template class bubble sort operand error

Hi i trying to create a template method to sort a vector of object by their x coordinate. They are giving me operand error with the '=' sign
Inside main have some codes, vector point2d have already data being populated.
vector<Point2D> point2d;
.....
point2d = sortByAscX(point2d, point2d.size());
my template.h
template <class T>
vector<T> sortByAscX(vector<T> a1, int size) {
for(int x=0; x<size; x++) {
for(int y=0; y<size-1; y++) {
if(a1[y].getX()<a1[y+1].getX()) {
int temp = a1[y+1].getX();
a1[y+1].setX(a1[y].getX());
a1[y].setX(temp);
}
}
}
return a1;
}
Error
MyTemplates.h:32:20: error: lvalue required as left operand of assignment
a1[y+1].getX() = a1[y].getX();
^
MyTemplates.h:34:18: error: lvalue required as left operand of assignment
a1[y].getX() = temp;
The reason you are getting this error is that you are calling a getX() function and trying to set it equal to a value. You need to have or call a setX() function and pass your value through it. You can only get a value with a get function.
As #NendoTaka correctly explained, you are trying to assign to a rvalue. If you want to use the same function for both a getter/setter, then make it return a reference
T& getX() { ...}
although now the name will be a tad confusing, as most people expect the getter to return an non-mutable object.
What does getX() return? It must not be an assignable value because that is what the compiler is complaining about. If it returns a reference of the X value, you can assign to it, but if it is const or returns a copy you can't assign to it.

who can tell me "*this pointer" in details?

for example,
in this one,
I 'm not very understand about the this pointer,
this question is not about operator+ overload,
is about the this pointer, and its relation between the class,
*this pointer point to what thing?
thank u very much!
class Integer {
int i;
public:
Integer(int ii): i(ii) { }
const Integer operator+(const Integer& rv) const {
cout<<"operator+"<<endl;
}
Integer&
operator+=(const Integer& rv) {
i += rv.i;
return *this;
}
}
thisidentifies a special type of pointer.IF you create an object named x of class A, and class A has a nonstatic member function f(). If you call the function x.f(), the keyword this in the body of f() stores the address of x. You cannot declare the this pointer or make assignments to it.
Basically this pointer is passed as a hidden argument to all nonstatic member function calls and is available as a local variable within the body of all nonstatic functions.
operator+= needs to return a reference to the current object (after it has been incremented) so that you can still write code such as
// UGLY CODE, ONLY TO ILLUSTRATE A POINT
Integer x, y;
x = (y += 10) + 1;
This form of the operator (taking a const reference, returning a reference) is also called the canonical form.
Where do you get the reference to return? You have this, which points to the current object, but you cannot return a pointer. So you dereference the pointer with operator* and return the result:
return *this;

Why does "return *this" return a reference?

In my C++ class they were discussing how to create an assignment operator. At the end of the assignment was the line "return *this," which they said returned a reference to the object that "this" points to. Why does it return a reference? If "this" is being dereferenced, shouldn't it just return the object?
A function returns a reference if its declaration (i.e. its signature) tells so.
So (assuming a class Foo) if a function is declarated
Foo fun();
then it returns a value (with copying, etc..)
But if it is declared as
Foo& fun();
or as
const Foo& fun();
a reference is returned.
The statement return *this; don't define by itself if a reference or a value is returned.
It returns the current instance of the type MyClass you are in. It's returned as reference because the assignment operator was explicitly told to return a reference.
MyClass& operator = (MyClass& other) { return *this; }
Note the & after MyClass as the return value. A reference is returned.
Unless the & weren't there right before operator, the instance would be returned by value.
The expression *this
At the end of the assignment was the line "return *this," which they said returned a reference to the object that "this" points to
They were wrong.
Why does it return a reference?
It doesn't.
If "this" is being dereferenced, shouldn't it just return the object?
Yes!
Dereferencing a pointer yields an lvalue. That means that the result of *this is the actual object that this points to. It's not a reference, but it's not a copy either.
[C++11: 5.3.1/1]: The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. If the type of the expression is “pointer to T,” the type of the result is “T.” [..]
It can be hard to conceptualise, since you can never do this yourself in code; it's just a feature of the * operator for native pointers, and has been since C.
Returning from operator=
Because you can't do it yourself, conventionally you'd bind that lvalue expression to a reference in order to use it in different contexts. For example, the expression *this in return *this gets bound to the return type of the function that you're returning from; in this case, an assignment operator.
Now, we could have the assignment operator return by value in which case an object copy would be made from the lvalue that comes from *this; however, for an assignment operator we usually return by reference so that we avoid an almost-certainly needless copy, and can perform chaining:
Type a, b, c;
c = b = a;
It's a convention with benefits, and no downsides. Can you think of a situation when you'd want op= to return by value?
Every dereferenced pointer is a reference to its pointee, else you'd 'loose' the pointee you're pointing to.
Invoke method twice on the same object, using a pointer and a reference:
MyClass* objPtr = .... ;
objPtr->doSomething();
MyClass& objRef = *objPtr;
objRef.doSomething();
Invoke method on distinct objects; original and copy:
MyClass* objPtr = .... ;
objPtr->doSomething();
MyClass objCopy = *objPtr; //here, the reference is passed to the (implicit or implemented) copy constructor if possible, else a compile time error occurs.
objCopy.doSomething();
That means, if you return a reference from an operator method which has MyClass (rvalue) instead of MyClass& (lvalue) as return type, a copy of *this (MyClass&) is created by reference (leaving aside return value optimizations and rvalue references).
This is useful for non modifying const methods such as + and - which have a new value as result while leaving the object on which this method was invoked unmodified.
Operators like += and your assignment operator modify the object inplace by convention and should therefore return a reference to allow expressions like primitive types support it, since a temporary copy may vanish and cause unexpected results:
Consider this expression:
int i = 4;
int r = (i += 3) <<= 2;
The result r is 28 (added and shifted inplace).
What is the value of i? 28 too, what else.
But what if hypothetically int::operator+= would return a copy of itself instead of a reference to itself?
The result r would be 28 too.
But the value of i?
It would be 7, since the inplace left shift was applied to a temporary int returned from the addition which gets assigned to r after that.
Continuing the assumption, the error may have the same effect (except for the value in i) as this expression:
int r = (i + 3) <<= 2;
But luckily, the compiler will complain, that he doesn't have an lvalue reference from (i + 3) to do the shift/assignment operation.
But play with this:
class Int
{
private:
int val;
public:
Int(int val) :
val(val)
{
}
Int operator+(const Int& other)const
{
return val + other.val;
}
Int operator+(int prim)const
{
return val + prim;
}
Int& operator+=(const Int& other)
{
val += other.val;
return *this;
}
//Error here, Int& would be correct
Int operator+=(int prim)
{
val += prim;
return *this;
}
Int operator<<(const Int& other)const
{
return val << other.val;
}
Int operator<<(int prim)const
{
return val << prim;
}
Int& operator<<=(const Int& other)
{
val <<= other.val;
return *this;
}
Int& operator<<=(int prim)
{
val <<= prim;
return *this;
}
operator int()const{
return val;
}
};
int main()
{
Int i = 4;
Int r = (i += 3) <<= 2;
cout << i;
return 0;
}
In C++ the * always means a value, in fact you can look to en English interpretation for these operators as follows:
&: the address of
*: the value of
So when you say &x it means "the address of x" and when you say *x it means "the value that x points to". So *this will always return a value.
Just be sure that the function itself that the hosts the returning is not a reference function. Please remember that in C++ you can create functions with the & or the * operators as well.

Please explain the following function

I have come across a function definition starting as:
int operator*(vector &y)
{
// body
}
After putting * just after operator and before opening brace of argument, what does this function mean?
This is an operator * overload. The syntax you should use is *(y) while y is of type vector.
It allows you a reference like implementation, something similar to pointer reference in C. Of course the actual meaning depends on the body. e.g. you can return a reference to an internal element in the vector.
This is a function overload for the * operator.
Its function overloading which overload the de-reference operator *.
It is either a dereferencing operator or a multiplication operator override. It is dereferencing if it is in a namespace and multiplication if it is inside a class. Since it has a body and no class scope I will also assume that it is a dereferencing.
Actually its not a deferencing operator as in *ptr! Its actually an operator such as a multiplication operator. Here is a simple example
#include <iostream>
using namespace std;
struct Int{
int val;
Int(const int val = 0) : val(val){}
int operator*(const Int& number)const{
return val * number.val;
}
};
int main(){
Int n(4), m(5);
cout << n * m << endl; //use the operator*() implicitly
cout << (n.operator*(m)) << endl; //use the operator* explicitly
}
To define a de-ferenceing operator, its prototype would be operator*(). Look here for more information. Here is a live code to test.