UFCS for D

Steven Schveighoffer schveiguy at yahoo.com
Thu Mar 29 17:09:30 PDT 2012


On Thu, 29 Mar 2012 19:46:24 -0400, Walter Bright  
<newshound2 at digitalmars.com> 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


More information about the Digitalmars-d-announce mailing list