On Thu, 10 Sep 2009 17:41:19 -0400, Rainer Deyke <[email protected]>
wrote:
Steven Schveighoffer wrote:
Sure, do whatever you want for your *private data members*. I see too
much value in Optional!T being aliased to the underlying T to go for the
completely generic solution which requires special syntax to get at the
T.
And I see no value at all, but a lot of danger. Even ignoring, what
about this:
void f(ref int v) {
// Do something...
}
void g() {
Optional!int x = 5;
f(x);
}
Doesn't compile. Implicit casting doesn't mean implicit reference casting.
Or this:
void report_error(int);
void f(T)(out T v) {
if (error_condition) throw new SomeException();
v = something;
}
void g() {
Optional!int v = someCalculation();
if (!isNull(v)) {
try {
f(v);
} catch (SomeException) {
report_error(v); // Oops, invalid: 'v' turned into null.
}
}
}
What is the point of this example? Use ref if you don't want f to change
the value of it's argument, not out.
Note how in the second example, the semantics of the function 'f' subtly
change depending on whether the argument is an 'int' or and
'Optional!int'.
Do they? I think the bug is that f's argument is out. What if the
argument is int, you get report_error(0), which tells you nothing. in
fact, you might as well just change the call to
report_error(typeof(v).init);
Proxies, especially proxies that add functionality to their base type,
cannot act exactly like the type they are proxying. Using a proxy
therefore requires the significant mental overhead of keeping track of
all the corner cases in which the proxy does not act like the type it is
proxying, as well as the hassle of working around those limitation
whenever they come up.
They can act like the base type up to a point. You make it sound like a
chore to use a wrapper type, but the truth is they are easy to use, there
are not that many cases to worry about.
-Steve