On Wed, Apr 29, 2015 at 02:53:03PM -0400, Ehsan Akhgari wrote:
> On 2015-04-27 9:54 PM, Trevor Saunders wrote:
> >On Mon, Apr 27, 2015 at 09:07:51PM -0400, Ehsan Akhgari wrote:
> >>On Mon, Apr 27, 2015 at 5:45 PM, Trevor Saunders <tbsau...@tbsaunde.org>
> >>wrote:
> >>
> >>>On Mon, Apr 27, 2015 at 03:48:48PM -0400, Ehsan Akhgari wrote:
> >>>>Right now, our coding style requires that both the virtual and override
> >>>>keywords to be specified for overridden virtual functions.  A few things
> >>>>have changed since we decided that a number of years ago:
> >>>>
> >>>>1. The override and final keywords are now available on all of the
> >>>>compilers that we build with, and we have stopped supporting compilers
> >>>that
> >>>>do not support these features.
> >>>>2. We have very recently gained the ability to run clang-based mass
> >>>source
> >>>>code transformations over our code that would let us enforce the coding
> >>>>style [1].
> >>>>
> >>>>I would like to propose a change to our coding style, and run a mass
> >>>>transformation over our code in order to enforce it.  I think we should
> >>>>change it to require the usage of exactly one of these keywords per
> >>>>*overridden* function: virtual, override, and final.  Here are the
> >>>>advantages:
> >>>
> >>>I believe we have some cases in the tree where a virtual function
> >>>doesn't override but is final so you need to write virtual final.  I
> >>>believe one of those cases may be so a function can be called indirectly
> >>>from outside libxul, and another might be to prevent people using some
> >>>cc macros incorrectly.
> >>>
> >>
> >>Any chance you could point us to those functions, please?
> >
> >http://mxr.mozilla.org/mozilla-central/source/xpcom/glue/nsCycleCollectionParticipant.h#548
> 
> Hmm, we can probably make an exception for this one.
> 
> >and this one isn't final, but we could make it final if the tu will be
> >built into libxul (because then devirtualization is fine)
> >http://mxr.mozilla.org/mozilla-central/source/dom/base/nsIDocument.h#1287
> 
> I'm not sure why that function is virtual.  If it's just in order to make it
> possible to call it through a vtable from outside of libxul, I'm not sure
> why we need to treat it differently than other XPCOM APIs for example.  If
> this is not used outside of libxul, we can probably make it non-virtual.

its the former.  We don't need to do anything special, but we could if
we wanted.  All that said it turns out its not terribly related.

> >>>>* It is a more succinct, as |virtual void foo() override;| doesn't convey
> >>>>more information than |void foo() override;|.
> >>>
> >>>personally I think it takes significantly more mental effort to read
> >>>void foo() final; to mean it overrides something and is virtual than if
> >>>its explicit as in virtual void foo() override final;
> >>>
> >>>and actually I'd also like it if C++ changed to allow override and final
> >>>on non virtual functions in which case this would be a loss of
> >>>information.
> >>>
> >>
> >>Well, we're not talking about changing C++.  ;-)  But why do you find it
> >
> >I didn't say we were, but should such a change happen this would then be
> >confusing.
> 
> C++ doesn't usually change in backwards incompatible ways, and for all
> practical intents and purposes we can proceed under the assumption that this
> will never happen, so we don't need to protect against it.

I don't think it would actually be backward incompatible the only
changes would be turning invalid programs into valid ones.

> >>more clear to say |virtual ... final| than |... final|?  They both convey
> >>the exact same amount of information.  Is it just habit and/or personal
> >>preference?
> >
> >its explicit vs implicit yes it is true that you can derive foo is
> >virtual from void foo() final; it doesn't take any habit or thinking to
> >see that from virtual void foo() override final; but I would claim its
> >not as obvious with void foo() final;  I don't think that's really a
> >preference more than say prefering text files to gziped files ;)
> 
> I disagree.  I understand the argument of someone not knowing these new
> keywords not understanding the distinction, but since we are already using
> these keywords, I think it is reasonable to expect people to either know or
> learn what these keywords mean.  And once they do, then it really becomes a
> matter of preference.
> 
> Another way to phrase this would be: if someone wonders whether foo in |void
> foo() final;| is virtual or not, they need to study the meaning of these
> keywords.  :-)

yes, but they also need to think about the meaning instead of just
reading.

> >>>>* It can be easily enforced using clang-tidy across the entire code base.
> >>>
> >>>That doesn't really seem like an argument for choosing this particular
> >>>style we could as easily check that virtual functions are always marked
> >>>virtual, and marked override if possible.
> >>>
> >>
> >>Except that is more tricky to get right.  Please see bug 1158776.
> >
> >not if we have a static analysis that checks override is always present.
> 
> We don't have that.  Please note that I'm really not interested in building
> a whole set of infrastructure just in order to keep the current wording of
> the coding style.  I agree that we could come up with ways of keeping the
> existing coding style, but this discussion is happening because I see no
> value in that work, and am arguing for changing that. So I'm more interested
> in arguments for why the current coding style is better, than how we can
> keep it working.

I think it'd be pretty trivial to add this check, the compiler already
does all the hard parts for you.  My point was that tooling isn't a
great reason to make either choice.

> >>>>* It makes it easier to determine what kind of function you are looking
> >>>at
> >>>>by just looking at its declaration.  |virtual void foo();| means a
> >>>virtual
> >>>>function that is not overridden, |void foo() override;| means an
> >>>overridden
> >>>>virtual function, and |void foo() final;| means an overridden virtual
> >>>>function that cannot be further overridden.
> >>>
> >>>this seems to be more an advantage of any enforced rule.  That is if we
> >>>just enforced that any function that overrides is marked override then
> >>>you would know that virtual void foo(); doesn't override, and otherwise
> >>>override would always be present which would make it clear it does
> >>>override in addition to possibly being final.
> >>>
> >>
> >>Yes, but again the point is that 1) one alternative repeats redundant
> >
> >sure, they're redundant if your only goal is to wwrite the shortest
> >possibleC++, but I'd claim if your goal is to write readable code they
> >are not redundant which is basically my whole point here.
> 
> The redundancy here hurts the readability of the code, because our brains
> will need to process what they read.  I'm explicitly not interested in
> optimizing for writing the shortest code.

I'd say it increases readability because while you read more you need to
think about what you read less, but I guess we're now at the point
that's just a diffrence in how our brains work ;)

> >>keywords, and 2) we don't *need* to use the virtual keyword on overriding
> >>functions any more.  Perhaps the second point is not clear from my first
> >>email.  Before, because not all of the compilers we target supported
> >>override and final, we *needed* to keep the virtual function, but now we
> >
> >no, we never *needed* to use virtual on overides that is
> >
> >class a { virtual void foo(); };
> >class b : a
> >{
> >     void foo();
> >};
> >
> >is perfectly valid C++.
> 
> Yes, but that would make it impossible to tell whether a method is virtual
> by just looking at its declaration, which hurts the readability of the code.

yes, it would certainly make things unpleasent, but that's not what the
word "need" means ;-)

> That's why we needed to use the virtual keyword before we could rely on the
> existence of the override keyword.
> 
> >>don't, so using virtual for overriding function now requires a
> >>justification, contrary to our past practice.
> >>
> >>
> >>>>* It allows us to be in sync with the Google C++ Style on this issue [2].
> >>>
> >>>I don't personally care about that much.
> >>>
> >>
> >>The reason why this is important is that many of the existing tools for
> >>massive rewriting of code bases have been written with that coding style in
> >>mind, so not diverging from that style enables us to use those tools out of
> >>the box.  (But this is just a nicety, of course.)
> >>
> >>
> >>>>* It will allow us to remove NS_IMETHODIMP, and use NS_IMETHOD instead.
> >>>
> >>>That doesn't really seem like much of an improvement, and of course
> >>>really we should just get rid of both but that's more work.
> >>>
> >>
> >>I don't understand how this is not an improvement.  I have seen *tons* of
> >>places where people are not sure which one they are supposed to use, or use
> >>the "wrong" one (for example, NS_IMETHODIMP for inline functions inside
> >>class bodies -- thankfully the virtual keyword is redundant.  ;-)
> >
> >Sure, it is a improvement, but the code implementing xpcom interfaces
> >over all probably isn't changing that much, and the total amount of such
> >code is slowely going down.  So it'll probably improve embedding/ a
> >bit, but that code will still be very unpleasent to read.
> 
> That's not really true.  We have a lot of XPCOM APIs that people use all the
> time, for example, nsIRunnable, nsIObserver, etc.

I guess it depends a lot what you work on.   ersonally I don't remember
the last time I wrote NS_IMETHOD[,IMP].

Trev

> 
> 
> Cheers,
> Ehsan
_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to