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.
Related
The spec is to overload the parenthesis () operator to access and assign elements of a matrix, however, I am struggling to figure out what my overload function needs to return.
The Brief Main:
//The .h files and everything has been included, my other functions work just not this one
cout << "Test (): " << endl;
m0(0,0) = 17.25;
m0(1,5) = -2.33;
m0(5,5) = 233; // There is class exception handling I just haven't included it
The Function Implementation:
Matrix* Matrix::operator () (const unsigned int m, const unsigned int n) //We were told they HAD to be unsigned int
{
Matrix *ptr = &matrix[m][n];
return ptr;
}
The Error:
main.cpp: In function ‘int main()’:
main.cpp:59:15: error: lvalue required as left operand of assignment
m0(0,0) = 17.25;
^~~~~
main.cpp:60:16: error: lvalue required as left operand of assignment
m0(1,5) = -2.33;
^~~~
main.cpp:61:15: error: lvalue required as left operand of assignment
m0(5,5) = 233; // should throw an exception
I understand what the error is saying, so please don't just tell me to read it again and fix it. I'm not actually sure how to fix what my function is returning and make it so the double values in the main can actually be assigned to something.
Thanks in advance
If you check this line in your program:
m0(0,0) = 17.25;
You are trying to assign a double value to the value returned by the () operator.
That means that you should return something that allows a double value assigned to it - and the easiest way to do it, is to return a double.
Also, because you want to assign something to it, you should return a reference - otherwise, you would just return a simple temporary value, and assignment isn't allowed for that. Even if the compiler would allow it, you wouldn't see the changes in your matrix, as you would change a temporary value.
I also see that in your current implementation, you are returning a pointer. Pointers are similar to references, but if you think about it, you can't directly assign a value to the memory pointed by a pointer - you have to dereference it first:
double* d = ...; // points to some memory
*d = 5;
And that's why a reference is better in this case.
In this template function, I am trying to retrieve at element from a boost ptr_map. I have omitted error handling code for clarity.
template <typename K, class T>
class A
{
public:
void TryGet(const K &key, T &o) { o = mObjects.at(key); }
private:
boost::ptr_map<K, T> mObjects;
};
typedef A<std::string, B> myClass;
I get the compiler error C2582: 'operator =' function is unavailable in 'B'. Why does the assignment of the return value of mObjects.at() to a reference need access to an assignment operator of the instantiated class? What is the correct way to return this value?
Why does the assignment of the return value of mObjects.at() to a reference need access to an assignment operator of the instantiated class?
When you are assigning to a reference, you are assigning to the object that the reference references.
int i = 0;
int& iRef = i; // There is no assignment, just initializing the reference.
iRef = 10; // Same as i = 10
Update, in response to OP's comment
What you are seeing is the equivalent of:
int j = 10;
int& jRef = j;
iRef = jRef; // Same as i = j
I think that you're asking "why can't I re-target a reference"?
What I mean by that is that you create a reference (let's call it ref1) that references a variable a (int& ref1 = a;) and then if you have another reference (ref2) that references a variable b (int& ref2 = b;`), you want to know why:
ref1 = ref2;
doesn't change ref1 to reference b, instead of doing a = b.
Is that correct?
If so, the answer is that "that's not now references work in C++". They can only be initialized once, and after that they cannot be changed.
Here's a discussion of this topic: Why are references not reseatable in C++
Now I get it. You don't know how references work in C++. Maybe your familiarity with Java is throwing you off track. In C++, references are simple aliases -- so you are attempting to assign directly to the object in question (which you have indicated is not legal). In Java, "references" are roughly the equivalent of C++ smart pointers. By wrapping your unnasignable types in those, you might be able to make this approach work.
boost::ptr_map<K, shared_ptr<T> > mObjects;
void TryGet(const K &key, shared_ptr<T> & o )
{
o = mObjects.at(key);
}
The problem of your code is
boost::ptr_map<K, T> mObjects;
boost::ptr_map need tow classes with overloaded assignment operator. You must overload assignment operator in Type B, if you want to use boost::ptr_map
My question is why it is possible to assign reference to a variable that is not declared as reference?
Thank you.
int &testRef(int &x)
{
return ++x;
}
int main()
{
int x = 1, y;
y = testRef(x); // assigning testRef(x) which is int& to y which is int
return 0;
}
y = testRef(x); will take a value copy of the reference returned by testRef. That can be useful if you want to make subsequent modifications to the return value.
If testRef were to return a const reference, then you'd have no choice but to take a value copy if you wanted to change the return value. That helps in achieving program stability.
Think of a reference as an alias, just a name of something. You're not assigning the reference. You're assigning the something that the reference names (or rather, that it references).
When passing by reference, actually nothing new is created, only an alias of original object being passed is created that points to the same object.
Literally, the 'x' parameter in the function() and the x being passed originally are the same.
By the way
int &testRef(int &x)
{
return ++x;
}
returning by reference makes it possible to assign rvalue : something like
int main()
{
int x = 1, y;
y = testRef(x);
testRef(y) = 5; //by doing this you are assigning y as 5
std::cout<<y;
return 0;
}
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.
In what situation would generate an error if you don't return something by reference for a function?
In what situation would generate an error if you don't return something by reference for a function?
Restricting the answer to what is being exactly asked,
Whenever you want the return value of the function to act as an l-value, and you do not return by reference then it will generate an error.
The more common example of this is overloading the operator [](the array subscription operator), You have to return by reference in order to use the [] on the l.h.s or more correctly to use it as an l-value.
An example:
class Myclass
{
int i;
public:
/*Not returned by reference- gives error*/
int operator[](int idx){ return i;}
/*Returned by reference- gives no error*/
//int& operator[](int idx){ return i;}
};
int main()
{
Myclass obj;
obj[1]= 10;
return 0;
}
Output:
prog.cpp: In function ‘int main()’:
prog.cpp:16: error: lvalue required as left operand of assignment
The default action should be to return by value. The main case where
you'ld want to return a reference is when you want to expose some
“part” of a larger object; e.g. an element in a vector or a
map. The important thing is that the object referred to must have a
lifetime beyond that of the calling function.
The question should be when is it not safe to return by reference. Whenever you return a variable local to a method by reference, you're invoking undefined behavior.
It's unsafe to return by value when you haven't correctly implemented the copy constructor.
You'd get an error if copy constructor was declared private and you'd try to return by value.