On Sunday, 9 December 2012 at 08:56:00 UTC, Maxim Fomin wrote:
On Sunday, 9 December 2012 at 07:39:29 UTC, js.mdnq wrote:
On Sunday, 9 December 2012 at 07:24:57 UTC, Jonathan M Davis
wrote:
On Sunday, December 09, 2012 07:54:25 js.mdnq wrote:
Why can't a struct inside a class access the members of that
class without a this pointer? It would seem natural to me
that a
nested struct should probably be special in that it is really
just a special container to reduce clutter in the class.
Without a this pointer, there are no class members to access,
because they
have to be associated with a specific instance of the class
unless they're
static. Non-static, nested structs have access to their
enclosing scope, but
then you can't create them separate from the enclosing class.
However, if you
declare a nested class to be static, it has no access to the
class' members
and is not associated with a specific instance of the class.
It's just that
it's declared inside the class instead of outside of it.
- Jonathan M Davis
NOOOOOOOOO!!!! It does have a this pointer!! If the sub-struct
is a true sub struct then it is inline inside the memory of
the class! That is, any member inside a struct can easily be
gotten from the pointer to the class(object) as one just has
to add a simple(and static) offset.
That is why nested struct inside a class actually does not have
a context pointer -its fields addresses are calculated as
offsets from class this pointer, not from struct this pointer.
If the struct is only used inside the class then there should
be no problem.
Problems comes when nested struct is created inside a function
without creating a class.
It makes no sense to have a struct inside a class behave
exactly as that outside as it offers no benefit to do so(or
maybe it does, but very little). Hence, we can redefine the
way structs behave inside classes to make them more useful.
Perhaps the situation can be improved.
In any case, take this example:
class A {
public:
string Name;
struct B { public: int x; alias x this; void func(A _a) {
writeln(_a.Name, x, y); }}
B x;
B y;
}
...
A a;
What is the address of A?
Meaning a, it is null.
What is the address of x inside A? (i.e., the struct inside A?)
x does not exists
Is it not a simple static offset from the address of A? i.e.,
knowing the address of a lets us know the address of x.
Knowing the address of x also lets us know the address of a!
(Same goes for y)
Yes, it is a CT-known offset which varies from one class to
another. Note, you can insert nested struct into another class.
This is why a nested struct(using my semantics) contains the
this pointer! (because it is a simple offset from the this
pointer which can be computed at compile time)!
That's why nested struct does not have this pointer - it is POD
structure.
http://dpaste.dzfl.pl/76e8ec0a
Yes, this is basically what I mean. structs to have addresses as
everything does in memory. But structs are created "inline". I do
not know what you mean x does not exist and the address of a. x
does exist(in the sense of any other variable) and a does have an
address.
You say
That is why nested struct inside a class actually does not have
a context pointer -its fields addresses are calculated as
offsets from class this pointer, not from struct this pointer.
But if this is true, and a difference between nested structs,
then there should be no issue implementing what I am talking
about.
What I am talking about would require the struct to only be used
inside the class as a class field. (as the struct is just
encapsulating members of the class and not meant to stand on it's
own, because, as you said, it would need a this pointer
associated with it)
With my method, I should easily be able calculate, from a
relative offset, the members of the class and use them. This
means that the compiler should be able to do it for me. It then
means that nested structs are not just structs stuck in a class
for who knows what reason but actually signify that they are
specially related to the class.
e.g.,
class A {
public:
string Name;
struct B {
int x;
void func(ref A tthis, int ofs)
{
byte *ptr = cast(byte*)tthis;
ptr += ofs;
writeln(*(cast(string*)(ptr)));
}
this(int y) { x = y; }
}
B b;
this() { Name = "test"; b = B(3); }
}
A a = new A();
a.b.func(a, 8);
prints "test" as expected.
B.func acts just like a member of A in that it takes a this
pointer just like any other member of A. It could be moved
outside of the struct into A.
Semantically there is little difference between using func inside
B or inside A EXCEPT that we have to provide the static offsets
and this ptr manually. If the compiler did it for us we would
could then use the struct as a way to provide encapsulation for
types inside the class so each could have it's own unique set of
overloads(as they won't then conflict with the class overloads).
This is the whole point. Obviously, a nested struct inside a
class has the ability to access it's class members(or, rather,
it's parents members) simply by "moving" all it's methods into
the class(but we see still think they are in the struct).
e.g., the above class has the exact same internal functionality
as this:
class A {
public:
string Name;
struct B {
int x;
this(int y) { x = y; }
}
B b;
void func()
{
writeln(Name);
}
this() { Name = "test"; b = B(3); }
}
(of course, we might have collisions now and we also have to call
func through A instead of B but we get the benefit of not having
to hard code the offset).