In this case, p is an address of g, or function pointer to foo?
int g;
@property ref int foo() { return g; }
auto p = &foo;
Until now, &foo always returns function pointer. If we want to get &g, we could write as like:
auto p = &foo(); // call foo first, then get an address of return value
But, if @property would be implemented more strictly, the syntax foo() will be disallowed. In other words, getting &g from &foo will be impossible. It is a serious flaw.
----
To resolve the problem, I'd like to propose a small special syntax: &(foo).
If AddrExp has a parenthesized expression, a property function in the operand will be resolved to property call.
pragma(msg, typeof( & foo )); // will print "int function() @property ref"
pragma(msg, typeof( &(foo) )); // will print "int*"
Comment #1 by github-bugzilla — 2012-11-22T22:24:20Z
If @property is all about equivalence of fields and accessors, then &foo should not return a function pointer. IMHO obtaining the funtion pointer should be the special case.
Comment #4 by k.hara.pg — 2012-11-23T04:57:35Z
(In reply to comment #3)
> If @property is all about equivalence of fields and accessors, then &foo should
> not return a function pointer.
Then, there is no way to get a function pointer from property function, right?
> IMHO obtaining the funtion pointer should be the
> special case.
std.traits.FunctionTypeOf!(property_func) is a special case?
Comment #5 by timon.gehr — 2012-11-23T05:00:33Z
Property functions should always be called regardless of context.
int g;
@property ref int foo() { return g; }
pragma(msg, typeof( & foo )); // will print "int*"
pragma(msg, typeof( &(foo) )); // will print "int*"
Comment #6 by timon.gehr — 2012-11-23T05:04:00Z
(In reply to comment #4)
> (In reply to comment #3)
> > If @property is all about equivalence of fields and accessors, then &foo should
> > not return a function pointer.
>
> Then, there is no way to get a function pointer from property function, right?
> ...
()ref => foo
Comment #7 by k.hara.pg — 2012-11-23T05:32:10Z
(In reply to comment #6)
> > Then, there is no way to get a function pointer from property function, right?
> > ...
>
> ()ref => foo
It looks like a lambda. Is it same as this?
ref __lambda() { return foo; }
But, on the return statement, foo is translated to foo(). It seems not possible.
Comment #8 by timon.gehr — 2012-11-23T05:41:30Z
(In reply to comment #7)
> (In reply to comment #6)
> > > Then, there is no way to get a function pointer from property function, right?
> > > ...
> >
> > ()ref => foo
>
> It looks like a lambda. Is it same as this?
>
> ref __lambda() { return foo; }
>
Yes, it is the same as &__lambda, where __lambda is
static ref __lambda() { return foo; }
(the fact that the parser chokes on ref-qualified function/delegate literals and function/delegate types is another bug.)
> But, on the return statement, foo is translated to foo(). It seems not
> possible.
&__lambda is a function pointer.
Comment #9 by k.hara.pg — 2012-11-23T06:06:46Z
(In reply to comment #8)
[snip]
OK, I understood what you say. But implementing it in library might be much difficult...
---
// An experimental implementation of timon's idea.
template PropertyTypeOf(alias prop)
{
auto ref wrapper()(){ return prop(); }
alias PropertyTypeOf = typeof(&wrapper!());
}
/*@property*/ int foo() @trusted nothrow { return 10;}
pragma(msg, PropertyTypeOf!foo);
// -> int function() nothrow @safe (not @trusted)
void main()
{
struct S { /*@property*/ string bar() pure { return ""; } }
pragma(msg, PropertyTypeOf!(S.bar));
// -> Error...
}
---
Comment #10 by timon.gehr — 2012-11-23T06:54:28Z
(In reply to comment #9)
> (In reply to comment #8)
> [snip]
>
> OK, I understood what you say. But implementing it in library might be much
> difficult...
>
> ---
> // An experimental implementation of timon's idea.
> template PropertyTypeOf(alias prop)
> {
> auto ref wrapper()(){ return prop(); }
> alias PropertyTypeOf = typeof(&wrapper!());
> }
>
> /*@property*/ int foo() @trusted nothrow { return 10;}
> pragma(msg, PropertyTypeOf!foo);
> // -> int function() nothrow @safe (not @trusted)
>
> void main()
> {
> struct S { /*@property*/ string bar() pure { return ""; } }
> pragma(msg, PropertyTypeOf!(S.bar));
> // -> Error...
> }
> ---
I am not sure what you are trying to do here. Anyways, the following should work:
template PropertyTypeOf(alias prop) {
alias PropertyTypeOf = typeof(()auto ref=>prop);
}
Comment #11 by k.hara.pg — 2012-11-25T01:51:06Z
(In reply to comment #10)
> I am not sure what you are trying to do here. Anyways, the following should
> work:
>
> template PropertyTypeOf(alias prop) {
> alias PropertyTypeOf = typeof(()auto ref=>prop);
> }
My try is an emulation of your idea. I found two problems at least.
1. In a way that uses template function attribute deduction, getting the @trusted attribute is impossible, because it is deduced to @safe.
2. Cannot get function type from member property function, because of 'need this' error.
Comment #12 by code — 2012-11-27T10:50:27Z
I would not worry to much about @trusted: In my »@trusted considered harmful« thread from a while back (http://forum.dlang.org/thread/[email protected]), nobody could come up with a reason for keeping it part of the interface. I just didn't get around to writing a DIP resp. implementing it in DMD yet.
Comment #13 by bugzilla — 2012-12-05T15:30:19Z
C++ has one special case where (e) means something different from e. (Few people know that case exists.)
Adding such to D makes me very nervous. I think it's a sound principle that any expression can be parenthesized without altering its meaning, it's important for anything that generates source code (like mixins are wont to do).
Comment #14 by k.hara.pg — 2012-12-05T16:26:04Z
(In reply to comment #13)
> C++ has one special case where (e) means something different from e. (Few
> people know that case exists.)
>
> Adding such to D makes me very nervous. I think it's a sound principle that any
> expression can be parenthesized without altering its meaning, it's important
> for anything that generates source code (like mixins are wont to do).
It's sure. But, &propfunc is one of the key point for the more property enforcement.
- If &propfunc returns an address of returned value, all function related meta templates will be broken (e.g. FunctionTypeOf).
- If &propfunc returns a function pointer of propfunc, all semantics are kept intact. But, to get an address of returned value from propfunc will become impossible in range of using built-in-language features.
I have thought a library solution, but this is ugly to me.
import std.algorithm : move;
T identity(T)( T t) { return move(t); }
ref T identity(T)(ref T t) { return t; }
int g;
@property ref int propfunc() { return g; }
void main() {
auto p1 = &propfunc; // p1 is function pointer
auto p2 = &identity(propfunc); // p2 is int*
// identity(propfunc) makes an expression,
// then getting an address of returned value can be succeeded.
assert(p2 == &g);
}
Comment #15 by bugzilla — 2012-12-05T16:37:04Z
I understand the ambiguity issue, and I am not proposing a solution. I'm just arguing against the e and (e) solution as (perhaps) causing more ambiguity problems.
Comment #16 by robert.schadek — 2024-12-13T18:02:58Z