Skip to content

Commit

Permalink
Merge pull request #370 from 9rnsr/enforceProp
Browse files Browse the repository at this point in the history
Add documentation for @Property attribute and optional parenthesis
  • Loading branch information
jmdavis committed Aug 8, 2013
2 parents 2770076 + dcceda1 commit af18032
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 49 deletions.
5 changes: 5 additions & 0 deletions attribute.dd
Expand Up @@ -27,6 +27,7 @@ $(GNAME Attribute):
$(RELATIVE_LINK2 shared, $(D shared))
$(RELATIVE_LINK2 gshared, $(D __gshared))
$(RELATIVE_LINK2 disable, $(D @disable))
$(RELATIVE_LINK2 property, $(D @property))


$(GNAME DeclarationBlock):
Expand Down Expand Up @@ -429,6 +430,10 @@ $(H3 $(LNAME2 disable, $(D @disable) Attribute))
makes the struct not copyable.
)

$(H3 $(LNAME2 property, $(D @property) Attribute))

$(P See $(XLINK2 function.html#property-functions, Property Functions)).

$(H3 $(LNAME2 override, Override Attribute))

$(P The $(D override) attribute applies to virtual functions.
Expand Down
73 changes: 41 additions & 32 deletions declaration.dd
Expand Up @@ -531,33 +531,33 @@ $(GNAME Typeof):
of an expression. For example:
)

--------------------
void func(int i) {
typeof(i) j; // j is of type int
typeof(3 + 6.0) x; // x is of type double
typeof(1)* p; // p is of type pointer to int
int[typeof(p)] a; // a is of type int[int*]

writefln("%d", typeof('c').sizeof); // prints 1
double c = cast(typeof(1.0))j; // cast j to double
}
--------------------
--------------------
void func(int i) {
typeof(i) j; // j is of type int
typeof(3 + 6.0) x; // x is of type double
typeof(1)* p; // p is of type pointer to int
int[typeof(p)] a; // a is of type int[int*]

writefln("%d", typeof('c').sizeof); // prints 1
double c = cast(typeof(1.0))j; // cast j to double
}
--------------------

$(P
$(I Expression) is not evaluated, just the type of it is
generated:
)

--------------------
void func() {
int i = 1;
typeof(++i) j; // j is declared to be an int, i is not incremented
writefln("%d", i); // prints 1
}
--------------------
--------------------
void func() {
int i = 1;
typeof(++i) j; // j is declared to be an int, i is not incremented
writefln("%d", i); // prints 1
}
--------------------

$(P There are three special cases: )
$(OL
$(OL
$(LI $(D typeof(this)) will generate the type of what $(D this)
would be in a non-static member function, even if not in a member
function.
Expand All @@ -568,26 +568,35 @@ void func() {
$(LI $(D typeof(return)) will, when inside a function scope,
give the return type of that function.
)
)

)
--------------------
class A { }

class B : A {
typeof(this) x; // x is declared to be a B
typeof(super) y; // y is declared to be an A
}

--------------------
class A { }
struct C {
static typeof(this) z; // z is declared to be a C

class B : A {
typeof(this) x; // x is declared to be a B
typeof(super) y; // y is declared to be an A
}
typeof(super) q; // error, no super struct for C
}

struct C {
static typeof(this) z; // z is declared to be a C
typeof(this) r; // error, no enclosing struct or class
--------------------

typeof(super) q; // error, no super struct for C
}
$(P If the expression is a $(XLINK2 function.html#property-functions,
Property Function), $(D typeof) gives its return type.
)

typeof(this) r; // error, no enclosing struct or class
--------------------
--------------------
struct S {
@property int foo() { return 1; }
}
typeof(S.foo) n; // n is declared to be an int
--------------------

$(P
Where $(I Typeof) is most useful is in writing generic
Expand Down
131 changes: 114 additions & 17 deletions function.dd
Expand Up @@ -233,27 +233,124 @@ $(OL

$(H4 $(LNAME2 property-functions, Property Functions))

$(P Property functions are tagged with the $(CODE @property)
attribute. They can be called without parentheses (hence
acting like properties).
$(P Property functions are tagged with the $(D @property)
attribute. They cannot be called with parentheses (hence
they act like fields except in some cases).
)

---
struct S {
int m_x;
@property {
int x() { return m_x; }
int x(int newx) { return m_x = newx; }
}
}
$(P If a property function has no parameters, it works as a getter.
If has exactly one parameter, it works as a setter.
)

---
struct S {
int m_x;
@property {
int x() { return m_x; }
int x(int newx) { return m_x = newx; }

int function(int, int) adder() {
return function int(int a, int b) { return a + b; }
}
}
}
void main() {
S s;
s.x; // lowered to s.x()
s.x = 3; // lowered to s.x(3)

//s.x(); // NG: lowered to s.x()(), but the int value
// returned by s.x() is not callable
//s.x(3); // NG: lowered to s.x()(3), but the int value
// returned by s.x() is not callable
assert(s.adder(1, 2) == 3);
// OK lowered to s.adder()(1, 2)
}
---

$(P If a getter property function returns a reference to other storage,
it also works as a setter.
)

---
struct S {
int m_x;
@property ref int x() { return m_x; }
}
void main() {
S s;
int n = s.x; // s.x()
assert(s.m_x == n);
s.x = 2; // s.x() = 2;
assert(s.m_x == 2);
}
---

$(P In most places, getter property functions are called immediately.
One exceptional case is the address operator.
)

---
struct S {
int m_x;
@property int x1() { return m_x; }
@property ref int x2() { return m_x; }
}
void main() {
S s;
auto x1 = &s.x1;
auto x2 = &s.x2;
static assert(is(typeof(x1) == delegate));
static assert(is(typeof(x2) == delegate));
// Both x1 and x2 are delegate, not int pointer.

int n = x1();
assert(s.m_x == n);
x2() = 1;
assert(s.m_x == 1);
}
---

$(P Even if the given operand is a property function, the address operator
returns the address of the property function rather than the address of
its return value.
)

void foo() {
S s;
s.x = 3; // calls s.x(int)
bar(s.x); // calls bar(s.x())
}
---

$(H4 $(LNAME2 optional-parenthesis, Optional parenthesis))

$(P If a function call does not take any arguments syntactically,
it is callable without parenthesis, like a getter $(RELATIVE_LINK2
property-functions, property functions).
)

---
void foo() {} // no arguments
void bar(int[] arr) {} // for UFCS

void main() {
foo(); // OK
foo; // also OK

int[] arr;
arr.bar(); // OK
arr.bar; // also OK
}
---

$(P However, assignment syntax is disallowed unlike with property functions.
)

---
struct S {
void foo(int) {} // one argument
}
void main() {
S s;
s.foo(1); // OK
//s.foo = 1; // disallowed
}
---

$(H4 $(LNAME2 virtual-functions, Virtual Functions))

Expand Down

0 comments on commit af18032

Please sign in to comment.