View mode: basic / threaded / horizontal-split · Log in · Help
December 09, 2012
alias this private?
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.
December 09, 2012
Re: alias this private?
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
December 09, 2012
Re: alias this private?
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.
December 09, 2012
Re: alias this private?
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...
December 09, 2012
Re: alias this private?
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
December 09, 2012
Re: alias this private?
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)
December 09, 2012
Re: alias this private?
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
December 09, 2012
Re: alias this private?
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?
December 10, 2012
Re: alias this private?
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
December 10, 2012
Re: alias this private?
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)
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home