Whats the significance of return by reference? - c++

In C++,
function() = 10;
works if the function returns a variable by reference.
What are the use cases of it?

The commonest case is to implement things like operator[].
struct A {
int data[10];
int & operator[]( int i ) {
return data[i];
}
};
Another is to return a big object from a class via an accesor function:
struct b {
SomeBigThing big;
const SomeBigThing & MyBig() const {
return big;
}
};
in order to avoid the copying overhead.

Consider the following code, MyFunction returns a pointer to an int, and you set a value to the int.
int *i;
i = MyFunction();
*i = 10;
Now shorten that to
*(MyFunction()) = 10;
It does exactly the same thing as the first code block.
You can look at a reference as just a pointer that's always dereferenced. So if my function returned a reference - not a pointer - to an int the frist code block would become
int &i;
i = MyFunction();
i = 10;
and the second would become
MyFunction() = 10;
This is what i was looking for

Getters/setters for instance
class C
{
int some_param_;
public:
int& param() { return some_param_; }
int const& param() const { return some_param_; }
};
but here you should go with some_param being a public int. Containers provide functions that return by reference, eg. vector<T>::operator[] so that you can write v[k] = x.

A very normal use case is when you write an array like class. Here you want to overload the operator [] so as you can do a[0] = 10; In that case you would want the signature to be like int& operator[](int index);

In case you have a class that contains another structure, it can be useful to directly modify the contained structure:
struct S
{
int value;
};
class C
{
public:
S& ref() { return m_s; }
private:
S m_s;
};
Allows you to write something like:
void foo()
{
C c;
// Now you can do that:
c.ref().value = 1;
}
Note: in this example it might be more straightforward to directly make m_s public rather than returning a reference.

SO screwed up my answer
You don't even need to return a reference:
struct C { };
C f() {
return C();
}
int main() {
C a;
f() = a; // compiles fine
}
Because this behavior is quite surprising, you should normally return a const value or a const reference unless the user has a sensible intent to modify the result.

It can be usefull when implementing accessors
class Matrix
{
public:
//I skip constructor, destructor etc
int & operator ()(int row, int col)
{
return m_arr[row + col * size];
}
private:
int size;
int * m_arr;
}
Matrix m(10);
m(1,0) = 10; //assign a value to row 1, col 0

Another classic case:
class Foo {
Foo();
public:
static Foo& getSingleton();
};

std::vector has operator[] which would not allow vec[n] = m otherwise.

You can also achieve method chaining (if you so desire) using return by reference.
class A
{
public:
A& method1()
{
//do something
return *this; //return ref to the current object
}
A& method2(int i);
A& method3(float f); //other bodies omitted for brevity
};
int main()
{
A aObj;
aObj.method1().method2(5).method3(0.75);
//or use it like this, if you prefer
aObj.method1()
.method2(5)
.method3(0.75);
}

The named parameter idiom is a another use case. Consider
class Foo
{
public:
Foo(
int lions,
float tigers,
double bears,
std::string zookeeper
);
};
users of this class need to remember the position of each parameter
Foo foo( 1, 2.0, 5, "Fred" );
which can be non-obvious without looking at the header. Compared to a creator class like so
class CreateFoo
{
friend class Foo;
public:
CreateFoo();
CreateFoo& lions(int lions) {
_lions = lions;
return *this;
}
CreateFoo& tigers(float tigers) {
_tigers = tigers;
return *this;
}
CreateFoo& bears(double bears) {
_bears = bears;
return *this;
}
CreateFoo& zookeeper(const std::string& zookeeper) {
_zookeeper = zookeeper;
return *this;
}
private:
int _lions;
float _tigers;
double _bears;
std::string _zookeeper;
};
which can then be used by clients like so
Foo foo = CreateFoo().
lions(1).
tigers(2.0).
zookeeper("Fred").
bears(5)
;
assuming Foo has a constructor taking a const CreateFoo&.

Related

Struct with array that changes dynamically

I have been looking to change dynamically the values of an array in a struct depending on other variables of the struct.
Let's say I have:
struct foo
{
int value1 = 0;
int value2 = 0;
int arr[2] = {value1, value2};
};
In the main if I have create an instance fooInstance and I want to associate a value to value1 fooInstance.value1 = 10, how can I update the value in the array ?
Thank you for your time.
Firstly, if you need an array, then I recommend storing the objects in the array directly.
I question the value (i.e. usefulness) of these aliases such as value1 when the name has no more meaning than referring to arr[i] directly. But I can see the value in case there is a descriptive name available. I'll use a more meaningful example of 2D vector with x, y dimensions. It should be easy to change float to int and change the names to match your attempt.
While Frank's solution using functions is great in most regards, it has a small caveat of having a less convenient syntax compared to variables. It's possible to achieve the variable syntax using operator overloading and anonymous unions. The trade-off is the increased boilerplate in the class definition. Example:
union Vector2 {
struct {
float a[2];
auto& operator=(float f) { a[0] = f; return *this; }
operator float&() & { return a[0]; }
operator const float&() const & { return a[0]; }
operator float () && { return a[0]; }
float* operator&() { return &a[0]; }
} x;
struct {
float a[2];
auto& operator=(float f) { a[1] = f; return *this; }
operator float&() & { return a[1]; }
operator const float&() const & { return a[1]; }
operator float () && { return a[1]; }
float* operator&() { return &a[1]; }
} y;
struct {
float a[2];
auto& operator=(float f) { a[0] = a[1] = f; return *this; }
float* begin() { return std::begin(a); }
float* end() { return std::end(a); }
} xy;
};
int main() {
Vector2 v2;
v2.xy = 1337; // assign many elements by name
v2.x = 42; // assign one element by name
std::cout << v2.x; // read one element by name
for(float f : v2.xy) { // iterate the entire array
std::cout << f;
}
}
Note to those unfamiliar with rules of unions: Reading from inactive union member is allowed only through common initial sequence of standard layout structs. This code is well defined, but the reader should be careful to not over generalise and assume that type punning through unions would be allowed; It isn't.
I adapted code from my earlier answer to another question.
It is different parameters coming from different hardwares.
This sounds like generating the accessors shown above with meta programming could be a good approach.
But, if you would like to avoid the complexity, then a more traditional approach would be to just use the array, and use enum to name the indices:
struct foo
{
int arr[100];
enum indices {
name1,
name2,
// ...
name100,
name_count,
};
};
int main()
{
foo f;
f.arr[foo.name1] = 42;
}
If at all possible, use encapsulation. That's the preferred way to create an interface/implementation skew:
struct foo
{
int& value1() { return arr_[0]; }
int& value2() { return arr_[1]; }
int* arr() { return arr_; }
private:
int arr_[2] = {0, 0};
};
void bar(foo& v) {
// access a single value
v.value1() = 3;
// access the whole array
v.arr()[0] = 5;
}
If you need access through both the individual member variables and through an array member variable, do not copy the data; rather, use the array as "the source of truth", and provide access through the individual variables or the individual member functions.
Here is your example rewritten to "alias" array variables to scalar member variables:
struct foo
{
foo() : value1(arr[0]), value2(arr[1]) {}
std::array<int,2> arr;
int& value1;
int& value2;
};
Note: this is not a good way of doing anything in production code, just an illustration of how the language lets you do something like this. Normally I would add accessor member-functions instead of member-variable references, because it avoids many problems referenced in the comments, such as breaking the value semantics.

how to forbid assignment to not reference variables?

I fear it's a dumb question but...
Someone can suggest me a way to force that a return value from a function (or a method), that return a reference to an internal static variable or a member of the class/struct, is assigned only to reference variables ?
I try to explain what I desire with a minimal example.
Given the following code, with a function wrapValue() that return a reference to the internal static variable,
int & wrapValue (int v0)
{
static int val;
return val = v0;
}
int main ()
{
// how to permit this ...
int & v0 { wrapValue(0) };
// ... but forbid this ...
int v1 { wrapValue(1) };
int v2;
// ... and this ?
v2 = wrapValue(2);
}
there is a way to permit the initialization of v0 (and bound v0 to the static variable) and forbid the initialization of v1 and the assignment of v2 (without bounding v1 and v2 to the static variable) ?
And if it's impossible with the current C++ standard, as I fear, someone can suggest me an alternative way (but not too complex: I intend use it in a library that I want to maintain simple) to forbid an unbounded assignment ?
This solution is somewhat tricky but it works (I think) as you expect:
#include <iostream>
struct int_wrapper {
int value;
int_wrapper &operator=(int value) {
this->value = value;
return *this;
}
operator int&() {
return value;
}
operator int() {
return value;
}
};
int_wrapper& wrapValue (int v0) {
static int_wrapper val;
return val = v0;
}
int main () {
// how to permit this ...
int & v0 = wrapValue(0);
// ... but forbid this ...
//int v1 { wrapValue(1) }; // call ambigious
int v2;
(void)v0;
(void)v2;
// ... and this ?
//v2 = wrapValue(2); // call ambigious
}
[live demo]
As far as I know int is copyable, so people can copy if they like; you cannot prevent this. However, you could create a wrapper class that is non-copyable.
class NonCopyableInt
{
int val;
public:
NonCopyableInt(int val) : val(val) {}
NonCopyableInt(NonCopyableInt&) = delete;
int& value() { return val; }
// todo: add some nice operators and functions such as assignment from int
}
NonCopyableInt& wrapValue (int v0)
{
static NonCopyableInt val;
return val = v0;
}
However, people could always copy the return value from value() so you end up with the same problem. And it feels really clunky and meh.

Replace member assignement with methods

After having produced some code in C++, it may be necessary to change the access to a member of a structure or class to something that produces some side effects. In that sense we would need to overload the assignement of a member to something different.
Struct A{
int v;
}
int main(){
A a;
a.v=17;
}
Is there the possibility to do it somehow ?
If there is not the possibility how would had been written the code in order to allow the flexibility to change a member into something more ?
The possibility of having each access to a memeber divided into a getter and setter seems coumbersome and impractical for any reasonable use.
Yes, use a proxy:
struct A
{
v_proxy v;
private:
struct v_proxy
{
v_proxy( int vv = 0 ) : v{ vv }
{}
//Write access
v_proxy& operator=( int i )
{
//Put your new code here
return v = i;
}
//Read access
operator int() const
{
return v;
}
int v;
};
};
int main()
{
A a;
a.v = 0;
};
Writting a generic proxy like this to allow the customization of read/writes in a common non- get/set syntax is easy.
EDIT: Some claim that this doesn't mimic correctly the behaviour of a C# property since in C# we can access this from the properties. Ok, just add a reference to the object and pass it to the proxy ctor. And don't forget to make the proxy class a friend of your class, to give that this reference full access:
class A
{
A() : v{ *this }
{}
friend struct v_proxy
{
v_proxy( A& ref , int vv = 0 ) : v{ vv } , This{ std::ref( ref )
{}
//Write access
int& operator=( int i )
{
//Put your new code here, for example:
This.foo();
return v = i;
}
//Read access
operator int() const
{
return v;
}
int v;
private:
std::reference_wrapper<A> This;
};

C++ access component via [""] or [int] for custom class

I've noticed things like what follows in C++.
SomeClass obj = SomeClass();
int boo = obj["foo"];
What is this called and how can I do it?
example
class Boo {
public:
int GetValue (string item) {
switch (item) {
case "foo" : return 1;
case "apple" : return 2;
}
return 0;
}
}
Boo boo = Boo();
int foo = boo.GetValue("foo");
// instead of that I want to be able to do
int foo = boo["foo"];
To use [], you'd overload operator[]:
class Boo {
public:
int operator[](string const &item) {
if (item == "foo")
return 1;
if (item == "apple")
return 2;
return 0;
}
};
You might be interested to know std::map already provides pretty much what you seem to be looking for:
std::map<std::string, int> boo;
boo["foo"] = 1;
boo["apple"] = 2;
int foo = boo["foo"];
The obvious difference is that when/if you use this to look up a value that hasn't previously been inserted, it'll insert a new item with that key and the value 0.
This is called operator overloading.
You need to define how the operator [] works:
#include <string>
class Boo {
public:
int operator[] (std::string item) {
if (item == "foo") return 1;
else if (item == "apple") return 2;
return 0;
}
};
Boo boo = Boo();
int foo = boo["foo"];
Also, the switch variable must have integral type so I changed to if else.
You need to overload the [] operator. Here is an example (oddly on a Java site).
What you want is overloading the subscript operator (operator[]); in your case you would do:
class Boo {
public:
int operator[](const string & item) const {
// you can't use switch with non-integral types
if(item=="foo")
return 1;
else if(item=="apple")
return 2;
else
return 0;
}
}
Boo boo = Boo();
int foo = boo["foo"];
Often classes that encapsulate containers return the data by reference, to allow the caller to modify the stored data; that's what most STL containers that provide operator[] do.

Is there some ninja trick to make a variable constant after its declaration?

I know the answer is 99.99% no, but I figured it was worth a try, you never know.
void SomeFunction(int a)
{
// Here some processing happens on a, for example:
a *= 50;
a %= 10;
if(example())
a = 0;
// From this point on I want to make "a" const; I don't want to allow
// any code past this comment to modify it in any way.
}
I can do something somewhat similar with const int b = a;, but it's not really the same and it creates a lot of confusion. A C++0x-only solution is acceptable.
EDIT: another less abstracted example, the one that made me ask this question:
void OpenFile(string path)
{
boost::to_lower(path);
// I want path to be constant now
ifstream ...
}
EDIT: another concrete example: Recapture const-ness on variables in a parallel section.
One solution would be to factor all of the mutation code into a lambda expression. Do all of the mutation in the lambda expression and assign the result out to a const int in the method scope. For example
void SomeFunction(const int p1) {
auto calcA = [&]() {
int a = p1;
a *= 50;
a %= 10;
if(example())
a = 0;
..
return a;
};
const int a = calcA();
...
}
or even
void SomeFunction(const int p1) {
const int a = [&]() {
int a = p1;
a *= 50;
a %= 10;
if(example())
a = 0;
..
return a;
}();
...
}
You could move the code to generate a into another function:
int ComputeA(int a) {
a *= 50;
a %= 10;
if (example())
a = 0;
return a;
}
void SomeFunction(const int a_in) {
const int a = ComputeA(a_in);
// ....
}
Otherwise, there's no nice way to do this at compile time.
A pattern I used to use is to "hide" the argument with an _, so the code becomes
void SomeFunction(int _a)
{
// Here some processing happens on a, for example:
_a *= 50;
_a %= 10;
if(example())
_a = 0;
const int a = _a;
// From this point on I want to make "a" const; I don't want to allow
// any code past this comment to modify it in any way.
}
You could also use only const variables and make a function to compute the new value of a, if necessary. I tend more en more to not "reuse" variables en make as much as possible my variables immutable : if you change the value of something , then give it a new name.
void SomeFunction(const int _a)
{
const int a = preprocess(_a);
....
}
Why not refactor your code in to two separate functions. One that returns a modified a and another that works on this value (without ever changing it).
You could possibly wrap your object too around a holder class object and work with this holder.
template <class T>
struct Constify {
Constify(T val) : v_( val ) {}
const T& get() const { return v_; }
};
void SomeFuncion() {
Constify ci( Compute() ); // Compute returns `a`
// process with ci
}
Your example has an easy fix: Refactoring.
// expect a lowercase path or use a case insensitive comparator for basic_string
void OpenFile(string const& path)
{
// I want path to be constant now
ifstream ...
}
OpenFile( boost::to_lower(path) ); // temporaries can bind to const&
this might be one way to do it, if you are just trying to avoid another name. i suggest you think twice before using this.
int func ()
{
int a;
a %= 10;
const int const_a = a;
#define a const_a
a = 10; // this will cause an error, as needed.
#undef a
}
I don't actually suggest doing this, but you could use creative variable shadowing to simulate something like what you want:
void SomeFunction(int a)
{
// Here some processing happens on a, for example:
a *= 50;
a %= 10;
if(example())
a = 0;
{
const int b = a;
const int a = b; // New a, shadows the outside one.
// Do whatever you want inside these nested braces, "a" is now const.
}
}
Answers were pretty solid, but honestly I can't really think of a GOOD situation to use this in. However in the event you want to Pre-Calculate a constant which is basically what you are doing you have a few main ways You can do this.
First we can do the following. So the compiler will simply set CompileA# for us in this case it's 50, 100, and 150.
const int CompileA1 = EarlyCalc(1);
const int CompileA2 = EarlyCalc(2);
const int CompileA3 = EarlyCalc(3);
int EarlyCalc(int a)
{
a *= 50;
return a;
}
Now anything beyond that there's so many ways you can handle this. I liked the suggestion as someone else had mentioned of doing.
void SomeFunc(int a)
{
const int A = EarlyCalc(a);
//We Can't edit A.
}
But another way could be...
SomeFunc(EarlcCalc(a));
void SomeFunc(const int A)
{
//We can't edit A.
}
Or even..
SomeFunction(int a)
{
a *= 50;
ActualFunction(a);
}
void ActualFunction(const int A)
{
//We can't edit A.
}
Sure, there is no way to do it using the same variable name in C++.