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

Reply via email to