On 02/08/2013 05:22 AM, deadalnix wrote:
...
You have the following behavior :
- & take the address of what is before.
- foo is call to function foo.
- special case : &foo
foo();
foo!()
tmpl!foo
alias sym=foo;
is the first class function foo. (here expression foo have a new meaning).
Again, & behaves like that even for variables.
auto x = 5;
auto y = &5; // error
auto z = &x; // ergo: this 'x' is different
assert(x==5); // from this one
- In a comma expression, if the last item is a function, it is
evaluated, unless the comma expression is in an address of context, in
which case the function pointer is returned.
- Same goes for ternary, except that both branches are evaluated in
that context.
This is exactly how special case (3) turtle down to definition of many
other languages constructs.
I think ternary and comma is a comprehensible list of the many other
language constructs.
For instance,
int a;
int foo() { return a }
static assert(is(typeof(foo) == typeof(a))); // Pass
condition ? foo : a; // OK.
&(condition ? foo : a); // Type error between foo of unexpressible type
(static array of instructions)
(This does not make any sense. Instructions are often variable-size.)
and a of type int.
The error message is a QOI issue. This is what DMD reports if foo is a
double, and a is an int:
Error: cast(double)a is not an lvalue
Error: cannot implicitly convert expression (condition ? & foo :
(__error)) of type double* to double*
(Another point: As you may have noticed, the constructs &(a?b:c) and
&(a,b) are "special cased" _anyway_.)
IMHO this is roughly what should be reported in both the case that foo
is a function and that foo is a double, maybe giving away a little more
information:
error: cannot take address of expression '(condition ? foo : a)'
&(condition ? foo : a);
^~~~~~~~~~~~~~~~~~~~~~
I think DIP24 is a valid way to go.
The simplest alternative design I'd be fine with would be to remove
@property, mandate parens on non-ufcs calls, identify function names
with their function pointers/delegates, disallow foo = functionArgument
and &foo for foo a function or method, and call it a day.
(This would not simplify lvalue/rvalue rules, but reduce the number of
cases where they apply.)