Thread overview
private is non-virtual: Stuck in C++-thinking?
Oct 19, 2012
Nick Sabalausky
Oct 19, 2012
monarch_dodra
Oct 19, 2012
Peter Alexander
Oct 19, 2012
Jonathan M Davis
Oct 23, 2012
deadalnix
Oct 23, 2012
Jonathan M Davis
Oct 19, 2012
foobar
Oct 20, 2012
Nick Sabalausky
Oct 20, 2012
monarch_dodra
Oct 23, 2012
deadalnix
October 19, 2012
My understanding is that this is intentionally disallowed:

---------------------------
module foo;

class Foo
{
    private void func() {}
}

class Bar : Foo
{
    // Disallowed:
    private override void func() {}
}

void foobar(Foo f)
{
    f.func();
}
---------------------------

If D had C++'s "private", that restriction would make a lot of sense (except possibly for nested classes, but I dunno). That's because: How can you override a class you can't even access?

But D doesn't have a "true" private in the C++ sense. Instead, there is code outside a class which *is* permitted to access "private" members.

So am I missing something, or was the sample case above overlooked when making the "private must be non-virtual" decision?

October 19, 2012
On Friday, 19 October 2012 at 21:09:05 UTC, Nick Sabalausky wrote:
> My understanding is that this is intentionally disallowed:
>
> ---------------------------
> module foo;
>
> class Foo
> {
>     private void func() {}
> }
>
> class Bar : Foo
> {
>     // Disallowed:
>     private override void func() {}
> }
>
> void foobar(Foo f)
> {
>     f.func();
> }
> ---------------------------
>
> If D had C++'s "private", that restriction would make a lot of sense
> (except possibly for nested classes, but I dunno). That's because: How
> can you override a class you can't even access?
>
> But D doesn't have a "true" private in the C++ sense. Instead, there
> is code outside a class which *is* permitted to access "private"
> members.
>
> So am I missing something, or was the sample case above overlooked when
> making the "private must be non-virtual" decision?

According to TDPL, this should be legal. In particular, there is
an entire section about it regarding NVI.

No idea what it going on, but I'm curious for answers.
October 19, 2012
On Friday, 19 October 2012 at 21:22:28 UTC, monarch_dodra wrote:
> On Friday, 19 October 2012 at 21:09:05 UTC, Nick Sabalausky
>> So am I missing something, or was the sample case above overlooked when
>> making the "private must be non-virtual" decision?
>
> According to TDPL, this should be legal. In particular, there is
> an entire section about it regarding NVI.
>
> No idea what it going on, but I'm curious for answers.

It's a bug.

http://d.puremagic.com/issues/show_bug.cgi?id=3581
http://d.puremagic.com/issues/show_bug.cgi?id=4542
October 19, 2012
On Friday, 19 October 2012 at 21:09:05 UTC, Nick Sabalausky wrote:
> My understanding is that this is intentionally disallowed:
>
> ---------------------------
> module foo;
>
> class Foo
> {
>     private void func() {}
> }
>
> class Bar : Foo
> {
>     // Disallowed:
>     private override void func() {}
> }
>
> void foobar(Foo f)
> {
>     f.func();
> }
> ---------------------------
>
> If D had C++'s "private", that restriction would make a lot of sense
> (except possibly for nested classes, but I dunno). That's because: How
> can you override a class you can't even access?
>
> But D doesn't have a "true" private in the C++ sense. Instead, there
> is code outside a class which *is* permitted to access "private"
> members.
>
> So am I missing something, or was the sample case above overlooked when
> making the "private must be non-virtual" decision?

virtual private is an obscure C++ idiom which I think the argument for is extremely week. I think Walter made the right decision here in favor of more readable code.

I'd do the following:
---------------------------
module foo;
class Foo {
    private void func() { funcImpl(); }
    protected void funcImpl() {}
}

class Bar : Foo {
    protected override void funcImpl() {}
}

void foobar(Foo f) {
    f.func();
}
---------------------------
October 19, 2012
On Friday, October 19, 2012 23:22:26 monarch_dodra wrote:
> According to TDPL, this should be legal. In particular, there is an entire section about it regarding NVI.
> 
> No idea what it going on, but I'm curious for answers.

For interfaces, where it's doing something to specifically enable NVI. It never says that for classes.

It's been discussed a number of times before, and I think that it's fairly clear that Walter has no intention of changing it. Regardless, it would actually be a _huge_ problem for private to be virtual, and it's completely unnecessary for NVI (protected does the job just fine). If private were virtual, then it that would kill inlining and any other optimization relying on knowing the body of the function or anything else which gets affected by a function being virtual - including the cost of the vtable lookup. You would be forced to mark all private functions as final to fix this, which most people won't do, which would lead to performance hits everywhere where classes are used. Classes in D would be less performant for essentially _zero_ gain.

If you want virtual but don't want the function to be public, then use protected.

- Jonathan M Davis
October 20, 2012
On Sat, 20 Oct 2012 00:18:28 +0200
"foobar" <foo@bar.com> wrote:
> 
> virtual private is an obscure C++ idiom which I think the argument for is extremely week.


Well like I said though, virtual private is *very* different in C++ than it is in D, because private itself is very different in C++ than in D.

> I think Walter made the right decision here in favor of more readable code.
> 

October 20, 2012
On Friday, 19 October 2012 at 22:18:29 UTC, foobar wrote:
>
> virtual private is an obscure C++ idiom which I think the argument for is extremely week. I think Walter made the right decision here in favor of more readable code.
>

Really? it is the entire point of NVI. I've seen it used all the time. It is even used (and documented) in the STL, as the way to customize streams...

On Friday, 19 October 2012 at 23:14:32 UTC, Jonathan M Davis wrote:
> On Friday, October 19, 2012 23:22:26 monarch_dodra wrote:
>> According to TDPL, this should be legal. In particular, there is
>> an entire section about it regarding NVI.
>> 
>> No idea what it going on, but I'm curious for answers.
>
> For interfaces, where it's doing something to specifically enable NVI. It never
> says that for classes.

Good point. I've not much experience with interfaces yet, so the difference didn't strike at me.

Yeah, once you define an interface, I guess the point of virtual private-ness becomes moot.
October 23, 2012
Le 20/10/2012 00:18, foobar a écrit :
> On Friday, 19 October 2012 at 21:09:05 UTC, Nick Sabalausky wrote:
>> My understanding is that this is intentionally disallowed:
>>
>> ---------------------------
>> module foo;
>>
>> class Foo
>> {
>> private void func() {}
>> }
>>
>> class Bar : Foo
>> {
>> // Disallowed:
>> private override void func() {}
>> }
>>
>> void foobar(Foo f)
>> {
>> f.func();
>> }
>> ---------------------------
>>
>> If D had C++'s "private", that restriction would make a lot of sense
>> (except possibly for nested classes, but I dunno). That's because: How
>> can you override a class you can't even access?
>>
>> But D doesn't have a "true" private in the C++ sense. Instead, there
>> is code outside a class which *is* permitted to access "private"
>> members.
>>
>> So am I missing something, or was the sample case above overlooked when
>> making the "private must be non-virtual" decision?
>
> virtual private is an obscure C++ idiom which I think the argument for
> is extremely week. I think Walter made the right decision here in favor
> of more readable code.
>
> I'd do the following:
> ---------------------------
> module foo;
> class Foo {
> private void func() { funcImpl(); }
> protected void funcImpl() {}
> }
>
> class Bar : Foo {
> protected override void funcImpl() {}
> }
>
> void foobar(Foo f) {
> f.func();
> }
> ---------------------------

Being able to define function but prevent from calling them is a very usefull thing. Especially when you want to allow to redefine behavior that would let the object in an invalid state.
October 23, 2012
Le 20/10/2012 01:14, Jonathan M Davis a écrit :
> On Friday, October 19, 2012 23:22:26 monarch_dodra wrote:
>> According to TDPL, this should be legal. In particular, there is
>> an entire section about it regarding NVI.
>>
>> No idea what it going on, but I'm curious for answers.
>
> For interfaces, where it's doing something to specifically enable NVI. It never
> says that for classes.
>
> It's been discussed a number of times before, and I think that it's fairly
> clear that Walter has no intention of changing it. Regardless, it would
> actually be a _huge_ problem for private to be virtual, and it's completely
> unnecessary for NVI (protected does the job just fine). If private were
> virtual, then it that would kill inlining and any other optimization relying
> on knowing the body of the function or anything else which gets affected by a
> function being virtual - including the cost of the vtable lookup.

Yes, if you don't want that, just define this a a private free function. D isn't some kind of language where everything need to be an object.
October 23, 2012
On Tuesday, October 23, 2012 21:34:35 deadalnix wrote:
> Le 20/10/2012 01:14, Jonathan M Davis a écrit :
> > On Friday, October 19, 2012 23:22:26 monarch_dodra wrote:
> >> According to TDPL, this should be legal. In particular, there is an entire section about it regarding NVI.
> >> 
> >> No idea what it going on, but I'm curious for answers.
> > 
> > For interfaces, where it's doing something to specifically enable NVI. It never says that for classes.
> > 
> > It's been discussed a number of times before, and I think that it's fairly
> > clear that Walter has no intention of changing it. Regardless, it would
> > actually be a _huge_ problem for private to be virtual, and it's
> > completely
> > unnecessary for NVI (protected does the job just fine). If private were
> > virtual, then it that would kill inlining and any other optimization
> > relying on knowing the body of the function or anything else which gets
> > affected by a function being virtual - including the cost of the vtable
> > lookup.
> 
> Yes, if you don't want that, just define this a a private free function. D isn't some kind of language where everything need to be an object.

That's no better than expecting programmers to mark all of their private functions final. It's not what they'll do normally, so they'll end up with slower code and complain about it. It just makes things slow by default, and being able to override private functions gains you pretty much _nothing_. _All_ that it does is make it impossible to call the base class implementation of the function. You can still call the implementation in the derived class. protected will do _exactly_ the same thing for you except that derived classes will be able to call the base class implementation rather than just their own. Making it impossible to call the base class implementation isn't even vaguely worth the performance costs that then affects almost every class ever written in D.

- Jonathan M Davis