www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - alias this private?

reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
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
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
next sibling parent "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Sunday, 9 December 2012 at 08:27:45 UTC, Ali Çehreli wrote:
 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
No, it doens't work on my version of D(2.058 I think). So maybe ok now.
Dec 09 2012
prev sibling parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
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
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Sunday, 9 December 2012 at 16:50:55 UTC, Ali Çehreli wrote:
 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
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)
Dec 09 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Sunday, 9 December 2012 at 19:38:28 UTC, Ali Çehreli wrote:
 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
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?
Dec 09 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Monday, 10 December 2012 at 04:50:17 UTC, Ali Çehreli wrote:
 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
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)
Dec 09 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Monday, 10 December 2012 at 07:48:37 UTC, Ali Çehreli wrote:
 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
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...
Dec 10 2012
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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