November 10, 2005
On Thu, 10 Nov 2005 02:56:49 +0200, Jari-Matti Mäkelä <jmjmak@invalid_utu.fi> wrote:
> Regan Heath wrote:
>> On Thu, 10 Nov 2005 02:34:36 +0200, Jari-Matti Mäkelä  <jmjmak@invalid_utu.fi> wrote:
>>
>>> Regan Heath wrote:
>>>
>>>> So, does Java have something like "friend" in C++? Does a class ever  gain  access to another classes 'private' data? If so, how? If not, why  has it  never been required? (as it was in C++? debatable?)
>>>
>>>
>>> Yes, all classes in the same package (Java package = D module) share  their private data. This is no problem (unless you run out of inodes ;))  since all non-friendly classes can be split into separate packages.
>>   Ahh, so that works like it does in D... only D calls them modules to  Java's packages and D have another thing called a "package" and a  protection attribute for that too.
>>
> Actually it's a bit more complex. Although packages in Java have many similarities with the modules in D, Java packages are physically (file system) like D packages. Actually Java packages may consist of multiple source files. Confusing, eh?

D has "packages" too, and they too consist of multiple files.

So, "package" in D is the same as "package" in Java, but, access to private members is restricted in D to modules as opposed to packages in Java.

Is that a good summary?

Regan
November 10, 2005
On Thu, 10 Nov 2005 15:06:17 +1300, Regan Heath wrote:

[big snip]

It would seem that we are not on the same wave length and I don't think I
can express myself well enough.

> I prefer D's method for it's simplicity.

Me too!

I just don't get what it is you can't understand in my text. I too am saying that D is got it mostly right! I would not want it to change its current behaviour or keywords --- with one tiny exception --- allow a new keyword to designate which class member are ONLY *accessible* to other members in that same class and to no other code anywhere.

Real example: I have a module that contains three class. These are big classes with lot's of functionality. This makes for a largish source file. They are in the same module because I *want* the D 'friend' behaviour for most of the members - for performance reasons mainly. However some members in one of the classes are strictly for the sole use of the code inside that class. And to save myself making mistakes, I'd love to designate those members as 'local' to the class and thus have the compiler trip over if I accidentally try to use them elsewhere. D does not support this form of self-protection. It doesn't mean that I can't write the application, but it does mean that I have greater chance of making a mistake. A compiler is also a tool to help people make fewer mistakes.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
10/11/2005 1:36:15 PM
November 10, 2005
In article <opszz5jlgs23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>On Thu, 10 Nov 2005 01:48:56 +0000 (UTC), Tomás Rossi <Tomás_member@pathlink.com> wrote:
>> In article <opszz0bk0623k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>>
>>> On Wed, 9 Nov 2005 21:50:19 +0000 (UTC), Tomás Rossi
>>> <Tomás_member@pathlink.com> wrote:
>>>> In article <opszzrvyj923k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>>>> The current D way offers no less control than "friend" in C++ but it offers it in a different way, instead of adding friend to a class you place it in the same module.
>>>>
>>>> What about if you have no access to the module source where lies the
>>>> class to
>>>> which you want your class to be friend with? (I know, my english
>>>> sucks).
>>>
>>> It's pretty good, that sentence is going to be confusing no matter how
>>> you
>>> say it.
>>>
>>>> The
>>>> friend approach gives you the advantage that you do not have to modify
>>>> the
>>>> source file of the class to which you want YOUR class to be friend
>>>> (that
>>>> could
>>>> be a class not written by you or you may even just not have the source,
>>>> maybe
>>>> just the .obj or .lib (is this not possible?)).
>>>> Correct me if i'm wrong please.
>>>
>>> I admin I am no C++ nor "friend" expert, it was my understanding that friend operates like so:
>>>
>>> class A {
>>>   private static int a;
>>>   friend class B;
>>> };
>>>
>>> class B {
>>>   void foo() { a = 5; }
>>> };
>>>
>>> class A specifies the friend who is allowed to access the private int
>>> 'a'
>>> and modify it. Without access to class A you cannot become a friend and
>>> access it's private members.
>>
>> For an example of what I mean, take a look of iostreams << and >>
>> operator
>> overloading. That was to what i was referring to.
>
>Take a look at what? the source code? (I assume you mean C++'s iostreams << and >> operators)

Think I was pretty obvious here.

>I'm not that well versed in C++ (mostly a C programmer) so I haven't used these, nor do I know how they're constructed. Can you give a simplified example?

I can give you a C++ not-compiled example (i'm opening the umbrella before it rains compiler errors or something):

In C++ there can be more specific friendship relation, not only friend classes.

Suppose I wrote a data structure, a container one:

#include <iostream>
#include "List.h"

template <class T>
class SimpleStack
{
private:
List<T> m_list;

public:
SimpleStack() {} // Constructor.
~SimpleStack() {} // Destructor.

size_t size() const { return m_list.size(); }
void push(const T& element) { m_list.pushFront(element); }
T pop() { return m_list.popFront(); }

friend ostream &operator<< <T> (ostream &os, const SimpleStack<T> &ss); };

// Implementation.
template <class T>
ostream &operator<<(ostream &os, const SimpleStack<T> &ss)
{
List<T>::ConstIterator it = ss.m_lista.begin();
while (it != ss.m_lista.end())
{
os << *it << endl;
it++; // Advance iterator.
}

return os;
}

then you could use it as:

int main()
{
SimpleStack<int> ss;
ss.push(3);
ss.push(-1);
ss.push(2);
cout << ss << endl;

return 0;
}

As you see, SimpleStack is permitting (through a "friend" declaration) to
implement an overloaded operator of ostream class, that causes you could just
use the << operator to print to the screen the SS object within a single and
nice line of code (a sort of toString()).

Ok, it's a little to much for this discussion maybe, but it may help to get clearer ideas of one of the motivations for wich we do friend declarations. I know this is not the way D enforce to do things (with respect to streams and screen output, i guess), so don't give me a preaching about this.

Tom
November 10, 2005
On Thu, 10 Nov 2005 03:11:52 +0000 (UTC), Tomás Rossi <Tomás_member@pathlink.com> wrote:
> In article <opszz5jlgs23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>
>> On Thu, 10 Nov 2005 01:48:56 +0000 (UTC), Tomás Rossi
>> <Tomás_member@pathlink.com> wrote:
>>> In article <opszz0bk0623k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>>>
>>>> On Wed, 9 Nov 2005 21:50:19 +0000 (UTC), Tomás Rossi
>>>> <Tomás_member@pathlink.com> wrote:
>>>>> In article <opszzrvyj923k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>>>>> The current D way offers no less control than "friend" in C++ but it
>>>>>> offers it in a different way, instead of adding friend to a class you
>>>>>> place it in the same module.
>>>>>
>>>>> What about if you have no access to the module source where lies the
>>>>> class to
>>>>> which you want your class to be friend with? (I know, my english
>>>>> sucks).
>>>>
>>>> It's pretty good, that sentence is going to be confusing no matter how
>>>> you
>>>> say it.
>>>>
>>>>> The
>>>>> friend approach gives you the advantage that you do not have to modify
>>>>> the
>>>>> source file of the class to which you want YOUR class to be friend
>>>>> (that
>>>>> could
>>>>> be a class not written by you or you may even just not have the source,
>>>>> maybe
>>>>> just the .obj or .lib (is this not possible?)).
>>>>> Correct me if i'm wrong please.
>>>>
>>>> I admin I am no C++ nor "friend" expert, it was my understanding that
>>>> friend operates like so:
>>>>
>>>> class A {
>>>>   private static int a;
>>>>   friend class B;
>>>> };
>>>>
>>>> class B {
>>>>   void foo() { a = 5; }
>>>> };
>>>>
>>>> class A specifies the friend who is allowed to access the private int
>>>> 'a'
>>>> and modify it. Without access to class A you cannot become a friend and
>>>> access it's private members.
>>>
>>> For an example of what I mean, take a look of iostreams << and >>
>>> operator
>>> overloading. That was to what i was referring to.
>>
>> Take a look at what? the source code? (I assume you mean C++'s iostreams
>> << and >> operators)
>
> Think I was pretty obvious here.

Obviously not :)

>> I'm not that well versed in C++ (mostly a C programmer) so I haven't used
>> these, nor do I know how they're constructed. Can you give a simplified
>> example?

<snip>

I understand what you mean now, you're saying C++ has friend functions as well as friend classes. So does D, any function in the same module as a class is a "friend" function.

Regan
November 10, 2005
In article <opszz9bmiy23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>On Thu, 10 Nov 2005 03:11:52 +0000 (UTC), Tomás Rossi <Tomás_member@pathlink.com> wrote:
>> In article <opszz5jlgs23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>>
>>> On Thu, 10 Nov 2005 01:48:56 +0000 (UTC), Tomás Rossi
>>> <Tomás_member@pathlink.com> wrote:
>>>> In article <opszz0bk0623k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>>>>
>>>>> On Wed, 9 Nov 2005 21:50:19 +0000 (UTC), Tomás Rossi
>>>>> <Tomás_member@pathlink.com> wrote:
>>>>>> In article <opszzrvyj923k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>>>>>> The current D way offers no less control than "friend" in C++ but it
>>>>>>> offers it in a different way, instead of adding friend to a class
>>>>>>> you
>>>>>>> place it in the same module.
>>>>>>
>>>>>> What about if you have no access to the module source where lies the
>>>>>> class to
>>>>>> which you want your class to be friend with? (I know, my english
>>>>>> sucks).
>>>>>
>>>>> It's pretty good, that sentence is going to be confusing no matter how
>>>>> you
>>>>> say it.
>>>>>
>>>>>> The
>>>>>> friend approach gives you the advantage that you do not have to
>>>>>> modify
>>>>>> the
>>>>>> source file of the class to which you want YOUR class to be friend
>>>>>> (that
>>>>>> could
>>>>>> be a class not written by you or you may even just not have the
>>>>>> source,
>>>>>> maybe
>>>>>> just the .obj or .lib (is this not possible?)).
>>>>>> Correct me if i'm wrong please.
>>>>>
>>>>> I admin I am no C++ nor "friend" expert, it was my understanding that friend operates like so:
>>>>>
>>>>> class A {
>>>>>   private static int a;
>>>>>   friend class B;
>>>>> };
>>>>>
>>>>> class B {
>>>>>   void foo() { a = 5; }
>>>>> };
>>>>>
>>>>> class A specifies the friend who is allowed to access the private int
>>>>> 'a'
>>>>> and modify it. Without access to class A you cannot become a friend
>>>>> and
>>>>> access it's private members.
>>>>
>>>> For an example of what I mean, take a look of iostreams << and >>
>>>> operator
>>>> overloading. That was to what i was referring to.
>>>
>>> Take a look at what? the source code? (I assume you mean C++'s iostreams
>>> << and >> operators)
>>
>> Think I was pretty obvious here.
>
>Obviously not :)

Ok, maybe I've assumed to much of your C++ knowledge here, sorry.

>>> I'm not that well versed in C++ (mostly a C programmer) so I haven't
>>> used
>>> these, nor do I know how they're constructed. Can you give a simplified
>>> example?
>
><snip>
>
>I understand what you mean now, you're saying C++ has friend functions as well as friend classes. So does D, any function in the same module as a class is a "friend" function.

Yap! :D, I think now we are in the same train of thought ;)
Thats what I meant. If you want to do something like this in D you just can't
because you're not supposed to add code to std modules (that would be iostream
in C++, a standard source files with standard objects the user isn't supposed to
touch), or to add code to someone else's modules to make the friendship, that's
obviously just an "YYYYAAACK, BAD BOY!" thing.

Tom
November 10, 2005
On Thu, 10 Nov 2005 13:51:15 +1100, Derek Parnell <derek@psych.ward> wrote:
> On Thu, 10 Nov 2005 15:06:17 +1300, Regan Heath wrote:
>
> [big snip]
>
> It would seem that we are not on the same wave length and I don't think I
> can express myself well enough.
>
>> I prefer D's method for it's simplicity.
>
> Me too!

I know!

> I just don't get what it is you can't understand in my text. I too am
> saying that D is got it mostly right! I would not want it to change its
> current behaviour or keywords --- with one tiny exception --- allow a new
> keyword to designate which class member are ONLY *accessible* to other
> members in that same class and to no other code anywhere.

I know!

My point, (which Tomás understood) is that your idea isn't flexible enough. It does not handle "protected" members i.e. a member which is protected externally but private or public internally. eg

[module.d]
class A {
  protected int a;
}

class B {
}

[other.d]
class C : A {
}

"local" cannot hide 'a' from class B and remain 'protected' in class C.

That is why I suggested making local a modifier for "private" etc, because then it can, eg.

[module.d]
class A {
  local protected int a;
}

class B {
}

[other.d]
class C : A {
}

you took my suggestion as an attempt to make your idea more complex, which I guess it does, but it also makes it a whole lot more useful.

Regan
November 10, 2005
On Thu, 10 Nov 2005 04:00:38 +0000 (UTC), Tomás Rossi <Tomás_member@pathlink.com> wrote:
> In article <opszz9bmiy23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>
>> On Thu, 10 Nov 2005 03:11:52 +0000 (UTC), Tomás Rossi
>> <Tomás_member@pathlink.com> wrote:
>>> In article <opszz5jlgs23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>>>
>>>> On Thu, 10 Nov 2005 01:48:56 +0000 (UTC), Tomás Rossi
>>>> <Tomás_member@pathlink.com> wrote:
>>>>> In article <opszz0bk0623k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>>>>>
>>>>>> On Wed, 9 Nov 2005 21:50:19 +0000 (UTC), Tomás Rossi
>>>>>> <Tomás_member@pathlink.com> wrote:
>>>>>>> In article <opszzrvyj923k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>>>>>>> The current D way offers no less control than "friend" in C++ but it
>>>>>>>> offers it in a different way, instead of adding friend to a class
>>>>>>>> you
>>>>>>>> place it in the same module.
>>>>>>>
>>>>>>> What about if you have no access to the module source where lies the
>>>>>>> class to
>>>>>>> which you want your class to be friend with? (I know, my english
>>>>>>> sucks).
>>>>>>
>>>>>> It's pretty good, that sentence is going to be confusing no matter how
>>>>>> you
>>>>>> say it.
>>>>>>
>>>>>>> The
>>>>>>> friend approach gives you the advantage that you do not have to
>>>>>>> modify
>>>>>>> the
>>>>>>> source file of the class to which you want YOUR class to be friend
>>>>>>> (that
>>>>>>> could
>>>>>>> be a class not written by you or you may even just not have the
>>>>>>> source,
>>>>>>> maybe
>>>>>>> just the .obj or .lib (is this not possible?)).
>>>>>>> Correct me if i'm wrong please.
>>>>>>
>>>>>> I admin I am no C++ nor "friend" expert, it was my understanding that
>>>>>> friend operates like so:
>>>>>>
>>>>>> class A {
>>>>>>   private static int a;
>>>>>>   friend class B;
>>>>>> };
>>>>>>
>>>>>> class B {
>>>>>>   void foo() { a = 5; }
>>>>>> };
>>>>>>
>>>>>> class A specifies the friend who is allowed to access the private int
>>>>>> 'a'
>>>>>> and modify it. Without access to class A you cannot become a friend
>>>>>> and
>>>>>> access it's private members.
>>>>>
>>>>> For an example of what I mean, take a look of iostreams << and >>
>>>>> operator
>>>>> overloading. That was to what i was referring to.
>>>>
>>>> Take a look at what? the source code? (I assume you mean C++'s iostreams
>>>> << and >> operators)
>>>
>>> Think I was pretty obvious here.
>>
>> Obviously not :)
>
> Ok, maybe I've assumed to much of your C++ knowledge here, sorry.
>
>>>> I'm not that well versed in C++ (mostly a C programmer) so I haven't
>>>> used
>>>> these, nor do I know how they're constructed. Can you give a simplified
>>>> example?
>>
>> <snip>
>>
>> I understand what you mean now, you're saying C++ has friend functions as
>> well as friend classes. So does D, any function in the same module as a
>> class is a "friend" function.
>
> Yap! :D, I think now we are in the same train of thought ;)
> Thats what I meant. If you want to do something like this in D you just can't because you're not supposed to add code to std modules (that would be iostream in C++, a standard source files with standard objects the user isn't supposed to touch), or to add code to someone else's modules to make the friendship, that's obviously just an "YYYYAAACK, BAD BOY!" thing.

Hold on. The code you posted had an operator<< overload, that overload was designated as a friend of SimpleStack<T> not of iostream, it has access to the private members of SimpleStack<T> not iostream. In order to achive that you had to modify SimpleStack<T> adding this line:

  friend ostream &operator<< <T> (ostream &os, const SimpleStack<T> &ss);

It's no different in D, you would have to place the operator overload in the same module as the SimpleStack<T> class.

Regan
November 10, 2005
Regan Heath wrote:
> One point however. Is there a difference between "visible" and  "accessable"? It seems "private" makes an instance (not a definition,  yet?) "inaccessable" but not "invisible", this is shown by the sort of  error message given when you try to access a "private" instance.
> 
> D's docs say that "private" replaces "static" but doesn't "static"  actually make an instance or declaration "invisible" as opposed to simply  making it "inaccessable", it seems "private" in D does not cover  everything that "static" did and that is why we're arguing about it ;)

Yes, that's true. The docs don't cover this issue very much. So you mean that although

  module a;
  private int i=42;

  module b:
  import a;
  printf("%d",i);		//illegal

is illegal, this example

  module a;
  private int i=42;

  module b:
  import a;
  printf("%d",b.i);	//maybe legal

might not be (at the moment).

I hope Walter has time to write better documentation. Now he focuses too much on class member visibility issues.
November 10, 2005
On Thu, 10 Nov 2005 10:01:39 +0200, Jari-Matti Mäkelä <jmjmak@invalid_utu.fi> wrote:
> Regan Heath wrote:
>> One point however. Is there a difference between "visible" and  "accessable"? It seems "private" makes an instance (not a definition,  yet?) "inaccessable" but not "invisible", this is shown by the sort of  error message given when you try to access a "private" instance.
>>  D's docs say that "private" replaces "static" but doesn't "static"  actually make an instance or declaration "invisible" as opposed to simply  making it "inaccessable", it seems "private" in D does not cover  everything that "static" did and that is why we're arguing about it ;)
>
> Yes, that's true. The docs don't cover this issue very much. So you mean that although
>
>    module a;
>    private int i=42;
>
>    module b:
>    import a;
>    printf("%d",i);		//illegal
>
> is illegal, this example
>
>    module a;
>    private int i=42;
>
>    module b:
>    import a;
>    printf("%d",b.i);	//maybe legal
>
> might not be (at the moment).

I think both are equally illegal. I think this last one is simply a bug.

What I was trying to say is that there is a difference between "invisible" and "inaccessable" a private variable is inaccessable but not invisible, this is why you get an error like:

[invis_a.d]
private int a;

[invis.d]
void main()
{
  a = 5; //invis.d: module invis invis_a.a is private
}

the compiler knows what 'a' you're talking about, it just wont let you, because it's "inaccessable".
as opposed to this from C:

[a.c]
static int a;

[test.c]
extern int a;

void main()
{
	a = 5; //test.obj : error LNK2001: unresolved external symbol _a
}

Here the compiler has no idea what 'a' you're talking about, it doesn't exist in this context, it's "invisible".

The difference is that static in C prevents the symbol 'a' from being visible outside the file a.c, whereas private in D simply prevents access to it. In C 'a' is invisible, in D 'a' is inaccessable.

I don't believe the D docs are 100% correct when they say:
http://www.digitalmars.com/d/attribute.html

"Private module members are equivalent to static declarations in C programs."

Regan
November 10, 2005
Regan Heath wrote:
> What I was trying to say is that there is a difference between "invisible"  and "inaccessable" a private variable is inaccessable but not invisible,  this is why you get an error like:
> 
> [invis_a.d]
> private int a;
> 
> [invis.d]
> void main()
> {
>   a = 5; //invis.d: module invis invis_a.a is private
> }
> 
> the compiler knows what 'a' you're talking about, it just wont let you,  because it's "inaccessable".
> as opposed to this from C:
> 
> [a.c]
> static int a;
> 
> [test.c]
> extern int a;
> 
> void main()
> {
>     a = 5; //test.obj : error LNK2001: unresolved external symbol _a
> }
> 
> Here the compiler has no idea what 'a' you're talking about, it doesn't  exist in this context, it's "invisible".
> 
> The difference is that static in C prevents the symbol 'a' from being  visible outside the file a.c, whereas private in D simply prevents access  to it. In C 'a' is invisible, in D 'a' is inaccessable.

Ok, now I got it :)

Yes of course, D & Java compilers have much more knowledge of symbols than the primitive C compiler. That's because D uses symbol tables, it doesn't just cut'n'paste those include-files.

> I don't believe the D docs are 100% correct when they say:
> http://www.digitalmars.com/d/attribute.html
> 
> "Private module members are equivalent to static declarations in C  programs."

I think it's bad practice to write docs that describe the functionality of the language by referring to other languages. Now you need to understand the concepts of several languages to understand D.