digitalmars.D.learn - alias this private?
- js.mdnq (14/14) Dec 08 2012 Can it not be possible to use alias this on a private field?
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (24/40) Dec 09 2012 I've just tested it. It is possible with dmd 2.060:
- js.mdnq (3/47) Dec 09 2012 No, it doens't work on my version of D(2.058 I think). So maybe
- js.mdnq (45/45) Dec 09 2012 Actually, it doesn't seem to work ;/ Your code worked but mine
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (83/88) Dec 09 2012 This is not adding to the discussion much but it is again because the
- js.mdnq (46/140) Dec 09 2012 but b is not private, only the internal representation of it.
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (23/56) Dec 09 2012 That is possible in D.
- js.mdnq (8/82) Dec 09 2012 Well, I would not say they are exactly the same. In your case you
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (32/41) Dec 09 2012 Do they have to be exactly the same? You are showing a method that fails...
- js.mdnq (20/67) Dec 09 2012 Na, it seems that my lack of knowing D is at fault. I thought
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (13/28) Dec 09 2012 No. 'alias value this' means "when this object is used in a context
- js.mdnq (7/44) Dec 10 2012 Yeah, basically it's close to what I was thinking but I guess the
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (9/14) Dec 10 2012 I may have been too subtle before but opGet() is not an operator
Can it not be possible to use alias this on a private field? struct Q private: int _x; public: alias _x this; ? Seems to me that one does not always want the user to access the internal value that is aliased ;/ Q q; q._x // error yet q, for all practical purposes is _x, we just stop the user from being able to directly access it. For example, maybe I want to override opAssign on an int. The user can get around it by doing q._x. Seems like a bad idea.
Dec 08 2012
On 12/08/2012 11:05 PM, js.mdnq wrote:Can it not be possible to use alias this on a private field?I've just tested it. It is possible with dmd 2.060: struct Q { private: int _x; public: alias _x this; } void main() { auto q = Q(); q = 42; assert(q._x == 42); }struct Q private: int _x; public: alias _x this; ? Seems to me that one does not always want the user to access the internal value that is aliased ;/Then the programmer should not "alias this" that member.Q q; q._x // error yet q, for all practical purposes is _x,q is for /some/ practical purposes is _x. :)we just stop the user from being able to directly access it.That is the case, because the member is private.For example, maybe I want to override opAssign on an int.Sorry, I could not understand that.The user can get around it by doing q._x. Seems like a bad idea.The user can't do that because _x is private. If they can, then it must be a bug. One thing that is confusing in D is that private members of a type are accessible by the module that includes that type. Is that the question? Ali
Dec 09 2012
On Sunday, 9 December 2012 at 08:27:45 UTC, Ali Çehreli wrote:On 12/08/2012 11:05 PM, js.mdnq wrote:No, it doens't work on my version of D(2.058 I think). So maybe ok now.Can it not be possible to use alias this on a private field?I've just tested it. It is possible with dmd 2.060: struct Q { private: int _x; public: alias _x this; } void main() { auto q = Q(); q = 42; assert(q._x == 42); }struct Q private: int _x; public: alias _x this; ? Seems to me that one does not always want the user to accesstheinternal value that is aliased ;/Then the programmer should not "alias this" that member.Q q; q._x // error yet q, for all practical purposes is _x,q is for /some/ practical purposes is _x. :)we just stop the user from being able to directly access it.That is the case, because the member is private.For example, maybe I want to override opAssign on an int.Sorry, I could not understand that.The user can get around it by doing q._x. Seems like a bad idea.The user can't do that because _x is private. If they can, then it must be a bug. One thing that is confusing in D is that private members of a type are accessible by the module that includes that type. Is that the question? Ali
Dec 09 2012
Actually, it doesn't seem to work ;/ Your code worked but mine does unless I make it public. It is a public/private issue and I get a ton of errors: module main; import std.stdio; class A { public: string Name; struct B(T) { private: //public: T Value; public: alias Value this; T opAssign(F)(F v) { //writeln(Name ~ " ..."); Value = cast(T)v; return Value; } } B!int b; } int main(string[] argv) { A c = new A(); c.b = 34; writeln(c.b); getchar(); return 0; } Error: template std.conv.toImpl does not match any function template declaration Error: template std.conv.toImpl cannot deduce template function from argument types !(int)(B!(int)) Error: template instance toImpl!(int) errors instantiating template Error: template instance std.conv.to!(int).to!(B!(int)) error instantiating So while it might "work" in the simple case it doesn't seem to actually work...
Dec 09 2012
On 12/09/2012 01:42 AM, js.mdnq wrote:Actually, it doesn't seem to work ;/ Your code worked but mine does unless I make it public. It is a public/private issue and I get a ton of errors:This is not adding to the discussion much but it is again because the member is private. writeln() is in a separate module, which cannot access a private member of another module. (Actually it is std.traits.isImplicitlyConvertible that can't access that member.): class A { struct B(T) { private: //public: T Value; public: alias Value this; T opAssign(F)(F v) { //writeln(Name ~ " ..."); Value = cast(T)v; return Value; } } B!int b; } // Copied from isImplicitlyConvertible template isImplicitlyConvertible_LOCAL(From, To) { enum bool isImplicitlyConvertible_LOCAL = is(typeof({ void fun(ref From v) { void gun(To) {} gun(v); } })); } import std.traits; int main(string[] argv) { A c = new A(); c.b = 34; static assert(isImplicitlyConvertible_LOCAL!(A.B!int, int)); // PASSES static assert(isImplicitlyConvertible !(A.B!int, int)); // FAILS return 0; }So while it might "work" in the simple case it doesn't seem to actually work...I am not sure that it should work. If it is private, maybe it should stay private. What you seem to need is read-only access to a private member. There are other ways of achieving that. The following program uses both a read-only property function and an 'alias this': module main; import std.stdio; class A { struct B(T) { private: //public: T Value_; public: // read-only accessor T Value() const property { return Value_; } // Automatic conversion to the read-only accessor alias Value this; T opAssign(F)(F v) { //writeln(Name ~ " ..."); Value_ = cast(T)v; return Value_; } } B!int b; } int main(string[] argv) { A c = new A(); c.b = 34; writeln(c.b); getchar(); return 0; } Ali
Dec 09 2012
On Sunday, 9 December 2012 at 16:50:55 UTC, Ali Çehreli wrote:On 12/09/2012 01:42 AM, js.mdnq wrote:but b is not private, only the internal representation of it. e.g., `alias Value_ this` is public. I do realize that it sort of makes Value_ and b one and the same but they are not quite the same. To me, it breaks encapsulation. writeln(c.b) is accessing b, not Value_. b is a "virtual type" in the sense that it wraps Value_. While it seems to do something funky like change the protection of Value_ from private to public it doesn't. There is no way to access Value_ when it is private. i.e., we can't do c.b.Value_; To drive the point home. We could/should be able to completely encapsulate `Value_` by overriding opAssign and add getters and setters so that `Value_` is actually never even used(although pointless then). Another way to see this: struct sPassword { private: string Password; public: alias this Password; opAssign opCast opCmp opGet { return "******"; } Change(old pass, new pass) { if ... } Validate(pass) { pass == Password; ... } } sPassword myPass; writeln(myPass) same as writeln(myPass.Get()) which prints ****** Such a type would be very secure. There is no way to get at Password(except through looking directly at memory, but we could encrypt it to make it difficult). But for all practical purposes myPass acts like a password. We can't accidently display the password to the user(in fact, there is no way unless a method is added to return the password, in which case there is no reason to make Password private. In any case, it just seems to me that we should be able to use private this way. If we want the additional functionality we just make it public. (it does sort of seem sPassword is like a readonly type but it's more than that as it encapsulates completely) Now, if Password was public instead of private, anyone could do myPass.Password to get the password. (the code isn't meant to be working D code but just a mix of pseudo and hypothetical D code)Actually, it doesn't seem to work ;/ Your code worked butmine doesunless I make it public. It is a public/private issue and Iget a ton oferrors:This is not adding to the discussion much but it is again because the member is private. writeln() is in a separate module, which cannot access a private member of another module. (Actually it is std.traits.isImplicitlyConvertible that can't access that member.): class A { struct B(T) { private: //public: T Value; public: alias Value this; T opAssign(F)(F v) { //writeln(Name ~ " ..."); Value = cast(T)v; return Value; } } B!int b; } // Copied from isImplicitlyConvertible template isImplicitlyConvertible_LOCAL(From, To) { enum bool isImplicitlyConvertible_LOCAL = is(typeof({ void fun(ref From v) { void gun(To) {} gun(v); } })); } import std.traits; int main(string[] argv) { A c = new A(); c.b = 34; static assert(isImplicitlyConvertible_LOCAL!(A.B!int, int)); // PASSES static assert(isImplicitlyConvertible !(A.B!int, int)); // FAILS return 0; }So while it might "work" in the simple case it doesn't seemto actuallywork...I am not sure that it should work. If it is private, maybe it should stay private. What you seem to need is read-only access to a private member. There are other ways of achieving that. The following program uses both a read-only property function and an 'alias this': module main; import std.stdio; class A { struct B(T) { private: //public: T Value_; public: // read-only accessor T Value() const property { return Value_; } // Automatic conversion to the read-only accessor alias Value this; T opAssign(F)(F v) { //writeln(Name ~ " ..."); Value_ = cast(T)v; return Value_; } } B!int b; } int main(string[] argv) { A c = new A(); c.b = 34; writeln(c.b); getchar(); return 0; } Ali
Dec 09 2012
On 12/09/2012 11:23 AM, js.mdnq wrote:but b is not private, only the internal representation of it. e.g., `alias Value_ this` is public. I do realize that it sort of makes Value_ and b one and the same but they are not quite the same. To me, it breaks encapsulation. writeln(c.b) is accessing b, not Value_. b is a "virtual type" in the sense that it wraps Value_. While it seems to do something funky like change the protection of Value_ from private to public it doesn't. There is no way to access Value_ when it is private. i.e., we can't do c.b.Value_;That's great. Value_ must remain private.To drive the point home. We could/should be able to completely encapsulate `Value_` by overriding opAssign and add getters and setters so that `Value_` is actually never even used(although pointless then).That is possible in D.Another way to see this: struct sPassword { private: string Password; public: alias this Password; opAssign opCast opCmp opGet { return "******"; } Change(old pass, new pass) { if ... } Validate(pass) { pass == Password; ... } } sPassword myPass; writeln(myPass) same as writeln(myPass.Get()) which prints ******You may have a point but at least I need to see how the existing features of D are not acceptable. The following already does what you want: struct sPassword { private: string Password_; public: alias opGet this; string opGet() { return "******"; } } void main() { sPassword myPass; assert(myPass == "******"); } (Aside: Although its name may suggest so, opGet is not an operator function.)In any case, it just seems to me that we should be able to use private this way. If we want the additional functionality we just make it public.Yes, private it good.(it does sort of seem sPassword is like a readonly type but it's more than that as it encapsulates completely) Now, if Password was public instead of private, anyone could do myPass.Password to get the password.Yeah, not a good idea. Ali
Dec 09 2012
On Sunday, 9 December 2012 at 19:38:28 UTC, Ali Çehreli wrote:On 12/09/2012 11:23 AM, js.mdnq wrote:Well, I would not say they are exactly the same. In your case you are aliasing on opGet while I'm talking about aliasing on the struct itself. e.g., there might be other members you do want the user to have access too. With your's, they won't be able to access them(your's is actually more restrictive). For example, how can they access a "Validate" method like I have using your struct?but b is not private, only the internal representation of it.e.g.,`alias Value_ this` is public. I do realize that it sort ofmakes Value_and b one and the same but they are not quite the same. To me, it breaks encapsulation. writeln(c.b) is accessing b,not Value_.b is a "virtual type" in the sense that it wraps Value_.While it seemsto do something funky like change the protection of Value_from privateto public it doesn't. There is no way to access Value_ whenit isprivate. i.e., we can't do c.b.Value_;That's great. Value_ must remain private.To drive the point home. We could/should be able to completely encapsulate `Value_` by overriding opAssign and add gettersand settersso that `Value_` is actually never even used(althoughpointless then). That is possible in D.Another way to see this: struct sPassword { private: string Password; public: alias this Password; opAssign opCast opCmp opGet { return "******"; } Change(old pass, new pass) { if ... } Validate(pass) { pass == Password; ... } } sPassword myPass; writeln(myPass) same as writeln(myPass.Get()) which prints****** You may have a point but at least I need to see how the existing features of D are not acceptable. The following already does what you want: struct sPassword { private: string Password_; public: alias opGet this; string opGet() { return "******"; } } void main() { sPassword myPass; assert(myPass == "******"); } (Aside: Although its name may suggest so, opGet is not an operator function.)In any case, it just seems to me that we should be able touse privatethis way. If we want the additional functionality we justmake it public. Yes, private it good.(it does sort of seem sPassword is like a readonly type butit's morethan that as it encapsulates completely) Now, if Password was public instead of private, anyone coulddomyPass.Password to get the password.Yeah, not a good idea. Ali
Dec 09 2012
On 12/09/2012 11:52 AM, js.mdnq wrote:Well, I would not say they are exactly the same.Do they have to be exactly the same? You are showing a method that fails to satisfy a requirement, I show another method which according to fail to satisfy another requirement. Software is engineering as well. What is the problem? Let's just solve it.In your case you are aliasing on opGet while I'm talking about aliasing on the struct itself.I know.e.g., there might be other members you do want the user to have access too.Then I give access to those members.With your's, they won't be able to access them(your's is actually more restrictive).I don't see that.For example, how can they access a "Validate" method like I have using your struct?It is so trivial that I am beginning to think I have not understood a tiny bit of what you have been saying, but here it goes: :) struct sPassword { private: string Password_; public: alias opGet this; void opAssign(string value) { Password_ = value; } string opGet() { return "******"; } bool Validate(string pass) { return pass == Password_; } } void main() { sPassword myPass; myPass = "hello"; assert(myPass == "******"); assert(myPass.Validate("hello")); // <-- here } I hope others can show me what I've been misunderstanding. :-/ Ali
Dec 09 2012
On Monday, 10 December 2012 at 04:50:17 UTC, Ali Çehreli wrote:On 12/09/2012 11:52 AM, js.mdnq wrote:Na, it seems that my lack of knowing D is at fault. I thought when you did alias this it essentially rewrote the object as the type... it seems that is not the case, at least, in what you have shown. Maybe it simply due to using opGet, which I did not know about until you brought it up? I thought `alias this` essentially treats the object as the alias. struct A { alias value this; int value; void func(); } A a; then a is essentially the same as a.value? a.func() would be a.value.func() which makes no sense? At least that is how I thought alias this worked? (it's obviously more complex than what I thought) (I'm new to D so you'll have to forgive all the stupid questions ;) D seems quite powerful and many useful ways to do things but I still haven't wrapped my head around all the intricacies)Well, I would not say they are exactly the same.Do they have to be exactly the same? You are showing a method that fails to satisfy a requirement, I show another method which according to fail to satisfy another requirement. Software is engineering as well. What is the problem? Let's just solve it.In your case you are aliasing on opGet while I'm talking about aliasing on thestruct itself. I know.e.g., there might be other members you do want the user tohave accesstoo.Then I give access to those members.With your's, they won't be able to access them(your's isactuallymore restrictive).I don't see that.For example, how can they access a "Validate" method like Ihave usingyour struct?It is so trivial that I am beginning to think I have not understood a tiny bit of what you have been saying, but here it goes: :) struct sPassword { private: string Password_; public: alias opGet this; void opAssign(string value) { Password_ = value; } string opGet() { return "******"; } bool Validate(string pass) { return pass == Password_; } } void main() { sPassword myPass; myPass = "hello"; assert(myPass == "******"); assert(myPass.Validate("hello")); // <-- here } I hope others can show me what I've been misunderstanding. :-/ Ali
Dec 09 2012
On 12/09/2012 10:43 PM, js.mdnq wrote:I thought `alias this` essentially treats the object as the alias. struct A { alias value this; int value; void func(); } A a; then a is essentially the same as a.value?No. 'alias value this' means "when this object is used in a context where the type of 'value' is expected, then use the 'value' member instead." In your example above, it means "when A is used in place of int, use 'value' instead." It is basically for automatic type conversion. (A reminder: Although the language spec allows multiple alias this declarations, current dmd supports only one.)a.func() would be a.value.func() which makes no sense?a.func() would still call A.func on object 'a' because 'a' is an A. Only when 'a' is used as an int, 'value' is considered.At least that is how I thought alias this worked? (it's obviously more complex than what I thought)Perhaps it is simpler than what you thought. :)(I'm new to D so you'll have to forgive all the stupid questions ;)Your questions make all of us learn more. :)D seems quite powerful and many useful ways to do things but I still haven't wrapped my head around all the intricacies)Indeed... There are a lot of features. Ali
Dec 09 2012
On Monday, 10 December 2012 at 07:48:37 UTC, Ali Çehreli wrote:On 12/09/2012 10:43 PM, js.mdnq wrote:Yeah, basically it's close to what I was thinking but I guess the opGet, which I'm still not familiar with, behaves a bit different when aliased. Possibly because we are aliasing a operator(or method?) which is different than aliasing a type? e.g., `alias opAssign this;` makes no sense to me ;/ Thanks for the help...I thought `alias this` essentially treats the object as thealias.struct A { alias value this; int value; void func(); } A a; then a is essentially the same as a.value?No. 'alias value this' means "when this object is used in a context where the type of 'value' is expected, then use the 'value' member instead." In your example above, it means "when A is used in place of int, use 'value' instead." It is basically for automatic type conversion. (A reminder: Although the language spec allows multiple alias this declarations, current dmd supports only one.)a.func() would be a.value.func() which makes no sense?a.func() would still call A.func on object 'a' because 'a' is an A. Only when 'a' is used as an int, 'value' is considered.At least that is how I thought alias this worked? (it's obviously more complex than what Ithought) Perhaps it is simpler than what you thought. :)(I'm new to D so you'll have to forgive all the stupidquestions ;) Your questions make all of us learn more. :)D seems quite powerful and many useful ways to do things butI stillhaven't wrapped my head around all the intricacies)Indeed... There are a lot of features. Ali
Dec 10 2012
On 12/10/2012 01:56 PM, js.mdnq wrote:I guess the opGet, which I'm still not familiar with, behaves a bit different when aliased. Possibly because we are aliasing a operator(or method?)I may have been too subtle before but opGet() is not an operator function. Although its name starts with op, it is still a member function.which is different than aliasing a type?The way I understand it, the compiler looks at the return type of that function and uses that function when the object is used instead of that type. If 'int foo()' is used in alias this, because foo() returns int, the object is eligible to be used in place of an int. foo() gets called to produce that int value. Ali
Dec 10 2012