Real overload or not ?

C

Christophe Bourez

Hi,

I am reviewing the coding guideline of an organisation and one of them
states that the name of the function members should start with an 'r'
if the function returns a non-const reference (I don't want to debate
whether returning a non-const ref is a good practice or not). Here
follows an example

class A
{
public:
int &rGetValue();
const int &GetValue() const;
....
};

Clearly, without the 'r', const and non const versions of GetValue
should have been considered as an overload . Prefixing the 'r' makes
obviously these member functions not real overload. Personally, I
really hate this kind of rule, but it is just a matter of taste. Could
you give me good reasons to prefer a real overload? For example, could
this kind of rule prevent the reuse of generic code, by the fact that
their names are not aligned?

Any opinion is really welcome and thank you in advance for your
contribution.

Christophe
 
Ö

Öö Tiib

Hi,

I am reviewing the coding guideline of an organisation and one of them
states that the name of the function members should start with an 'r'
if the function returns a non-const reference (I don't want to debate
whether returning a non-const ref is a good practice or not).

If you are reviewing then you are apparently asked for your opinion.
Why our opinion matters?
Here follows an example

class A
{
public:
    int &rGetValue();
    const int &GetValue() const;
...

};

Clearly i do not like const int&. I always pass int there.
Clearly, without the 'r', const and non const versions of GetValue
should have been considered as an overload . Prefixing the 'r' makes
obviously these member functions not real overload. Personally, I
really hate this kind of rule, but it is just a matter of taste. Could
you give me good reasons to prefer a real overload? For example, could
this kind of rule prevent the reuse of generic code, by the fact that
their names are not aligned?

Generics should assume to get non-const references from very few
places like operator=, operator* (unary) and operator[] these you can
not prefix with r anyway.
Any opinion is really welcome and thank you in advance for your
contribution.

My opinion is that passing non-const reference is bad practice unless
the class under question is container-like or pointer-like. With
container-like their rule is also bad since it causes a member named
'rat':

value_type const& at( size_type n ) const;
value_type& rat( size_type n );

As for pointer-like classes these usually overload the operators. For
navigating ( next(), prev(), up(), down(), left(), right() ) you pass
a pointer or pointer-like and not a reference since it is possible
that you are at edge and have to pass NULL. I am out of cases where i
need something that passes non-const reference with non-operator and
non-rat. ;)
 
M

Michael Tsang

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Öö Tiib said:
My opinion is that passing non-const reference is bad practice unless
the class under question is container-like or pointer-like. With
container-like their rule is also bad since it causes a member named
'rat':
Bad practice? I think it is good if the function modifies the arguments.

e.g.

template<class t>void swap(t &a, t &b) {
t &&c = std::move(a);
a = std::move(b);
b = std::move(c);
}

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAktcKwUACgkQm4klUUKw07AGTwCdGPa9qXuqqpV9vn4VMvsRQVyE
fW0AnRoPMD690Okp++3keyX7p37jf/jI
=yFK8
-----END PGP SIGNATURE-----
 
A

Abhishek Padmanabh

Hi,

I am reviewing the coding guideline of an organisation and one of them
states that the name of the function members should start with an 'r'
if the function returns a non-const reference (I don't want to debate
whether returning a non-const ref is a good practice or not). Here
follows an example

class A
{
public:
    int &rGetValue();
    const int &GetValue() const;
...

};

Clearly, without the 'r', const and non const versions of GetValue
should have been considered as an overload . Prefixing the 'r' makes
obviously these member functions not real overload. Personally, I
really hate this kind of rule, but it is just a matter of taste. Could
you give me good reasons to prefer a real overload? For example, could
this kind of rule prevent the reuse of generic code, by the fact that
their names are not aligned?

It would cause the user of the class to be aware of the const-ness of
the object if he wants to make changes to the reference to the member
returned by calling the non-const version. Which means:

//consider you have an object of A named a
//I would need to have:
int & ref = a.rGetValue();

Irrespective of a being const or non-const, the const member function
gets called.

It would not affect generic code, because if it is possible to achieve
the functionality with the const version, you really don't need to
have the non-const function to be called. Which means, if there is a
function like:

void f(const A& a)
{
a.GetValue();
}

a.GetValue() would be sufficient even though the input object for f()
is a const A or a non-const A. But, this is a very different naming
convention you have. May be, the intention was to be able to identify
the locations where the non-const reference to the member was being
returned without going into the debate around if returning a non-const
reference to a member is good or bad. And may be, to prevent
accidentally, getting back a non-const reference to a member and then
the user code accidentally changing it directly or indirectly, while
with the convention, any such change would happen by an explicit call
to rGetValue like members and in those case the user code is fully
aware of what its doing.
 
Ö

Öö Tiib

Bad practice? I think it is good if the function modifies the arguments.

e.g.

template<class t>void swap(t &a, t &b) {
        t &&c = std::move(a);
        a = std::move(b);
        b = std::move(c);

}

Yes, i was mistyping 'passing'. I meant member function 'returning'
non-const references. Sorry, bad English.
 
S

SG

template<class t>void swap(t &a, t &b) {
        t &&c = std::move(a);
        a = std::move(b);
        b = std::move(c);
}

....is perfectly valid C++ and doesn't invoke undefined behaviour. But
it also doesn't do what you want. In your case "c" is just another
alias of object "a" refers to. It should have been

t c {std::move(a)};

As for const-overloading, I believe the upcoming C++ standard will add
"cbegin" and "cend" to all container classes so you can easily get
const_iterators from a non-const container. So, it seems it's not
*that* bad.

Cheers,
SG
 
J

James Kanze

I am reviewing the coding guideline of an organisation and one
of them states that the name of the function members should
start with an 'r' if the function returns a non-const
reference (I don't want to debate whether returning a
non-const ref is a good practice or not). Here follows an
example
class A
{
public:
int &rGetValue();
const int &GetValue() const;
...
};

That smacks of Hungarian. In the bad sense. On the other hand,
it is quite normal for a function which allows or supports
modification of internal state to have a different names, or at
least a different signature, from one which doesn't. After all,
they're doing different things. Thus, one would expect:
int GetValue() const;
void PutValue(int newValue);
or
int value() const;
void value(int newValue);
(To give the two most frequent conventions.)

About the only case I can think of where a const and a non-const
function should be overloaded is for operator overloading.
Clearly, without the 'r', const and non const versions of GetValue
should have been considered as an overload.

Which is something you definitely want to avoid. It's the means
which are bad, not the end.
Prefixing the 'r' makes obviously these member functions not
real overload. Personally, I really hate this kind of rule,
but it is just a matter of taste. Could you give me good
reasons to prefer a real overload?

Obfuscation? The possibility to create obscure bugs?
For example, could this kind of rule prevent the reuse of
generic code, by the fact that their names are not aligned?

No.
 

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

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top