Return by reference behave as rvalue or lvalue

I'm working on an assignment that involves return by reference the goal is to have a member function return by reference and have it behave as an rvalue or lvalue depending on how it's called if the object is const. Here is what I got.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//Header declaration
ELEMENT_TYPE const &at( const int &position );

// member function definition

template<class ELEMENT_TYPE>
ELEMENT_TYPE const &Array<ELEMENT_TYPE>::at( const int &position )
{
    return (mv_array[position - mv_lowBound]);
}

// My main program

#include <iostream>
#include "array.h"

using namespace std;

// I'm trying to get the function to behave properly when the object is const.

void constTest (const SafeArray<string> &data , int pos)
{
  cout << "Const Test" << data.at(pos) << endl << endl; // Should be legal.
  data.at(pos) = "NA NA NA"; // Should not be legal.
  cout << data.at(pos) << endl;
}


int main()
{

int low = 0;
int high = 15;
char x = 'a';
Array<char> a(high);
for (int i = 0 ; i <= high ; ++i)
{
a.set(i, x++);
cout << a.get(i) << endl;
}
a.at(low) = 'z';
cout << a.get(low) << endl;


cout << "Array Size in bytes: " << a.size() << endl;
cout << "Upbound: " << a.upperBound()  << endl;
cout << "LowBound: " << a.lowerBound()  << endl;
cout << "Number of elements in the Array:  " << a.numElements() << endl << endl;


SafeArray<string> b(high , low);

string y = "blah";
for (int i = 0 ; i <= high ; ++i)
{
b.set(i,y);
cout << b.get(i) << endl;
}

b.at(low) = "Batman";
cout << b.at(low) << endl;

cout << "Array Size in bytes: " << b.size() << endl;
cout << "Upbound: " << b.upperBound()  << endl;
cout << "LowBound: " << b.lowerBound()  << endl;
cout << "Number of elements in the Array:  " << b.numElements() << endl << endl;

constTest(b , low);

return 0;


If anyone wants complete code, let me know. I'll post the full length.
I know that it has something to do with const correctness, and probably some other stuff I'm not understanding.

Thanks!
Chris
Last edited on
I think is what you are looking for (just an example, but you should be able to adapt it):
1
2
3
4
5
6
7
8
9
class C {
  int myint;
  const int& the_val() const { //return const reference if the C instance is const
     return myint;
  }
  int& the_val() { //return mutable reference if the C instance is mutable
     return myint;
  }
};

I didn't actually compile this so I may be forgetting something, though.
I'll give it a shot and see what happens. In my lecture handout, there is something about returning *this. But I'm not seeing if that has something to do with this or not. Thanks for the help!
That solved it, thanks!
Keep in mind (for when you get out of that class) that both function calls in this case are lvalues.
Is there a particular way to make a member function return by reference and have it return an lvalue or rvalue when appropriate?

The code Zhuge gave works. at() is illegal when a lvalue, and legal as an rvalue. It seems to work. Is there something I'm missing?

All I really did was make two functions as shown above.

1
2
3
4
5
6
7
8
9
10
11
template<class ELEMENT_TYPE>
const ELEMENT_TYPE &Array<ELEMENT_TYPE>::at( const int &position ) const
{
    return (mv_array[position - mv_lowBound]);
}

template<class ELEMENT_TYPE>
ELEMENT_TYPE &Array<ELEMENT_TYPE>::at( const int &position )
{
    return (mv_array[position - mv_lowBound]);
}
Is there a particular way to make a member function return by reference and have it return an lvalue or rvalue when appropriate?


No, but there is no reason the const version must return a reference, and I don't think Cubbi meant for you to infer that an lvalue expression here isn't appropriate. The important thing in this situation is maintaining const correctness (which is probably what your instructor was trying to convey,) and the "valueness" of the expression type is orthogonal to that goal.

The code Zhuge gave works. at() is illegal when a lvalue, and legal as an rvalue.


I think you mean the return from at() is assignable when the object it is invoked on is not const and isn't assignable when the object at() is invoked on is const, as one would expect from a const object.

You may find the following to be interesting reading:
http://eli.thegreenplace.net/2011/12/15/understanding-lvalues-and-rvalues-in-c-and-c/

Thanks for that link, very helpful. Sounds like I'm going to need work on my mental model of these concepts...
Topic archived. No new replies allowed.