On Thu, 29 Mar 2012 19:46:24 -0400, Walter Bright
<[email protected]> wrote:
On 3/29/2012 4:34 PM, Steven Schveighoffer wrote:
One
misleading suggestion from the article however, it's not very easy to
create
non-friend non-member functions using UFCS, considering that every
function in a
given module is a friend. In order to do this, you would need a helper
module
for each module that wants to define such non-friend functions. Given
the above
proof, the helper module would also have to be imported by the main
module.
I think there's a misunderstanding. The class should contain, as member
functions, anything that needs to access private state. UFCS functions
declared in other modules should not need access to private state (if
they do, it's an error in the design of the class) and so should have no
problem being non-friends.
I don't think it's a misunderstanding on my part. If you read Scott's
article (as I did a week or so ago when I realized this limitation), he
makes this point:
class A
{
private:
int x;
public:
int getX() { return x; }
int getXSquared() { return getX() * getX(); }
}
Is more encapsulated with getXSquared moved *outside* the class like this:
int getXSquared(A &a) { return a.getX() * a.getX(); }
and use namespaces to make sure there is no symbol conflict.
The reason being, if you change anything in class A, you do not have to
worry about the implementation of getXSquared, because it simply has no
access to the private implementation. You only have to worry about
internal methods, and friend functions.
The intention is, getXSquared is a fundamental part of A's interface, so
it actually is defined in the same location as A. That is, it's not an
afterthought defined elsewhere, it's part of A's API that should always be
with A.
In order to accomplish this in D, getXSquared must go into another
module. There is no mechanism to say "don't give this function access to
A's private data". While I think Scott's arguments are a little strict in
light of how D doesn't define explicit friendship, he has a good point.
The D compiler doesn't help you achieve this goal *at all*.
In fact, in order to achieve UFCS with this, you'd have to define the
getXSquared method in a helper module, and the module defining A must
include the helper, which must include the original module. This creates
a module cycle, so that means you can only have static ctor/dtors in one
or the other. This makes things even more awkward.
-Steve