Re: Implicit conversions for value subtyping
On Apr 22, 6:59 pm, ?? Tiib <oot...@hot.ee> wrote:
On Apr 19, 3:04 pm, David Barrett-Lennard <davi...@iinet.net.au>
wrote:
The following uses structs (public member variables) without
suggesting that is necessarily appropriate.
struct Square { int s; };
int side(Square sq) { return sq.s; }
You pass Square by value, and that is bad idea when Square represents
something with enough properties (that even squares have like
location, color, inclination degree ... etc.) to pass it by reference.
Better is:
int side(Square const& sq) { return sq.s; }
Yes I implied that was a valid option in the original post. With in-
lining it's unlikely to make any difference. In this particular case
if the compiler really did pass by reference it could well be slower
because of the indirection.
struct Rect
{
Rect(Square s) : w(side(s)), h(side(s)) {}
This causes often secret overhead, you may get conversion copy where
you did not expect it. I usually put explicit in front of it.
Yes but the whole point of this exercise was to allow implicit
conversions.
void Test()
{
Square s = {10};
int A = area(s);
}
If you did not make Rect constructor explicit then it works. Otherwise
you have to write:
int A = area(Rect(s));
That indicates to possible reader that conversion takes place. So if
they want to optimize (and graphics people often do) then they write:
inline int width(Square const& sq) { return side(sq); }
inline int height(Square const& sq) { return side(sq); }
inline int area(Square const& sq) { return
width(sq)*height(sq); }
As results most compilers generate equivalent of:
int A = 100;
That happens with modern compilers anyway with my original example, so
writing all that extra code is unnecessary.
Questions:
1) Is this a reasonable technique?
I avoid it. In large project such implicit conversions cause sometimes
hard to discover bugs because they hide simple typos.
Implicit conversions can be classified as safe or dangerous depending
on whether there are surprises. I believe I gave a safe one that is
very unlikely to be the source of bugs. Indeed all things being
equal, more concise code tends to have fewer bugs. If you think
otherwise I would appreciate a realistic example.
2) Is there a reason why C++ was designed so that const member
functions defeat the implicit conversions on *this?
I don't think that they do. I think that your own const-correctness
and pass-by-value defects defeat it. Try if it works:
Where was there a const-correctness defect?
Pass by value is hardly a "defect" (at least in the code I presented).
struct Square { int s; int foo() const; };
int side(Square const& sq) { return sq.s; }
struct Rect
{
Rect(Square const& s) : w(side(s)), h(side(s)) {}
int w, h;
};
int width(Rect const& r) { return r.w; }
int height(Rect const& r) { return r.h; }
int area(Rect const& r) { return width(r) * height(r); }
int Square::foo() const { return area(*this); }
void Test()
{
Square s = {10};
int A = area(s);
int F = s.foo();
}
Actually I meant that a const member function Rect::area() cannot
allow implicit conversions when attempting to use it to find the area
of a Square. The result is that in C++ free functions are much better
behaved for value-types. Indeed this is a common reason for using
friend functions.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]