"explicit pass-by-reference" idiom

S

SG

Hi!

This is not a question. I just wanted to share some thoughts on
passing pointers or references to functions. I tend not to think about
it too hard whether to use a pointer or a reference as function
parameter but there are obviously certain (minor) advantages and
disadvantages for each approach.

class A;

void foo(A* ptr);
void bar(A& ref);

void g(A& a) {
foo(&a);
bar(a);
}

We can see at the call sites for foo and bar that foo obviously takes
a pointer whereas bar may take a reference or an object by value (we
need to see the declaration of bar to be sure). I guess that being
explicit about it at the call site may sometimes lead to more readable
code -- at least when the function can mutate the object. But on the
other hand foo might not be able to handle null pointers. The fact
that references always refer to an object (if they're not already
dangling) is nice. A way to do both, being "explicit" at the call site
and avoiding null pointers is what C# achieves with its keyword "ref",
for example. The upcoming C++ standard library will provide something
similar, "reference wrappers". So, i could do something like this:

#include <functional>
template<class T> using refw = std::reference_wrapper<T>;
using std::ref;
using std::cref;

void foobar(refw<A> a);

void g(A& a) {
foobar(ref(a));
}

So, if you feel the need to avoid null pointers and be explicit at the
call site about the function taking a reference you could use a
reference_wrapper like this.

Unfortunately, there is no implicit conversion from
reference_wrapper<U> to reference_wrapper<T> in case U* is implicitly
convertible to T*. I guess this feature has been forgotten or hasn't
yet come up as something nice-to-have.

Cheers,
SG
 
K

Kai-Uwe Bux

SG said:
Hi!

This is not a question. I just wanted to share some thoughts on
passing pointers or references to functions. I tend not to think about
it too hard whether to use a pointer or a reference as function
parameter but there are obviously certain (minor) advantages and
disadvantages for each approach.

class A;

void foo(A* ptr);
void bar(A& ref);

void g(A& a) {
foo(&a);
bar(a);
}

We can see at the call sites for foo and bar that foo obviously takes
a pointer whereas bar may take a reference or an object by value (we
need to see the declaration of bar to be sure). I guess that being
explicit about it at the call site may sometimes lead to more readable
code -- at least when the function can mutate the object. But on the
other hand foo might not be able to handle null pointers. The fact
that references always refer to an object (if they're not already
dangling) is nice. A way to do both, being "explicit" at the call site
and avoiding null pointers is what C# achieves with its keyword "ref",
for example. The upcoming C++ standard library will provide something
similar, "reference wrappers". So, i could do something like this:

#include <functional>
template<class T> using refw = std::reference_wrapper<T>;
using std::ref;
using std::cref;

void foobar(refw<A> a);

void g(A& a) {
foobar(ref(a));
}

So, if you feel the need to avoid null pointers and be explicit at the
call site about the function taking a reference you could use a
reference_wrapper like this.
[...]

I am not saying that it is a good idea, but I wonder: what is wrong with

template < typename T >
T& ref ( T& arg ) {
return ( arg );
}

and now, if and where you want to be explicit, you could write

bar( ref(a) ); // was bar(a)

I see that your approach forces being explicit at every call site, this one
doesn't.


Best

Kai-Uwe Bux
 
S

SG

I am not saying that it is a good idea, but I wonder: what is wrong with

  template < typename T >
  T& ref ( T& arg ) {
    return ( arg );
  }

and now, if and where you want to be explicit, you could write

  bar( ref(a) );   // was bar(a)

True. Alternatives: a do-nothing macro or just a comment like

bar( /*ref*/ a );

but...
I see that your approach forces being explicit at every call site,

....being forced to use it was part of the idea.

Cheers,
SG
 
K

Kai-Uwe Bux

SG said:
True. Alternatives: a do-nothing macro or just a comment like

bar( /*ref*/ a );

but...


...being forced to use it was part of the idea.

Hm, I don't think I like the notion of a library inflicting the authors
coding styles upon me as the client. That will lead to quite checkered code
when libraries from different sources are used together, each pushing their
own notion of "clear code".


Best

Kai-Uwe Bux
 
B

Bo Persson

SG said:
True. Alternatives: a do-nothing macro or just a comment like

bar( /*ref*/ a );

Aren't we back at the hungarian notation again? :)

If you want to see that a function might modify its parameters, just
avoid calling it bar!

If I have a function call

update(a);

I would be very annoyed if it did not modify a.


Bo Persson
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top