On 27/08/2013 02:48, Lex Trotman wrote:
Hi Nick,

Thanks for the well thought out sensible proposal.  In general I agree with
the idea of progressively moving appropriate parts of the code to using
appropriate C++ features.  Of course, as usual, I disagree on some of the
details and I'm sure we would disagree on some of the selections of files,
but thats healthy.

Thanks for considering it ;-)

I now think gradually using a (quite heavily restricted) subset of C++98
for *some* source files might be better than moving to C99 (more on that
below). I still support C99 over just C90 though. (I don't do a lot of
Geany coding now, but I plan to do some from time to time, so obviously
this is just my opinion and less important than more active devs).


I'll address the "restricted subset" idea here and refer back from relevant
places below.  My experience of a couple of projects migrating to C++ is
that applying strict "limits" on the C++ features just leads to
implementing those features poorly in the code itself.  One common one is
to not allow virtual functions, but in my experience that just leads to the
use of function pointers and the associated ugly syntax and increase in
errors.

If we want to write OOP code, allow "virtual" and "class". Personally I tend to think for Geany OOP is mostly useful for GTK. If we want that, we would need gtkmm bindings.

Another reason why I suggest we don't use OOP is that getting overloading right with inheritance is difficult for C++ beginners, and can cause bugs with experienced devs. Avoiding OOP simplifies the unintuitive corner cases of C++, and is easier for C programmers.

The approach that seems to have worked better is the same as that required
for C++ in general, *appropriate* use of features.  Whilst that is easier
to control in a corporate situation where programmers can be trained
properly, review by senior devs should catch the more egregious misuses
within Geany, its not like we have a huge developer base to train anyway :).

We have a fairly large potential contributor base.

Reasons:

* No build problems for Long Term Support distros that don't support C99
(but clearly do compile scintilla's C++98).


Neil is attempting to move Scintilla forward, it might soon be using C++03.5

Another project was against Neil moving to C++11, not just us. Nice though C++11 is. As things stand though, we know using more C++98 won't cause problems for users. C99 possibly might. C++11 may do.

* RAII - this is a pretty essential feature for safe resource management.
It's a stupid acronym though, it's basically automatic scoped destruction:

http://en.wikipedia.org/wiki/**Resource_Acquisition_is_**Initialization<http://en.wikipedia.org/wiki/Resource_Acquisition_is_Initialization>


Agree on both the usefulness and the silly name :)

:)

* References can be useful in making code more readable vs pointers.


Unfortunately, since references are immutable, you can never get rid of
pointers in imperative style programs, that leads to code with a mix,
luckily getting it wrong (using . not ->) will be picked up by the compiler.

I don't want to use references instead of pointers, only where references make the code easier to maintain. E.g. 'Output' arguments and sometimes in local scope to simplify repeated expressions.

* Developer enjoyment, productivity & gaining more experience with C++.
(This might be an incentive for e.g. me to spend more time working on
Geany). This has to be offset against those that might need to learn e.g.
RAII.


Indeed there is a learning curve, but hopefully many will find that useful
and attractive.

+1

* Possibly we could use a GObject wrapper for safe reference counting. I
don't want to add any dependencies on C++ libraries though.


Or what almost all my C++03 programs have, a template headed:  /* The
ubiquitous intrusive reference counted smart pointer */ :)

Of course use gobject, for things that are gobjects, but don't bring it
into things that are not, the idea is to move to C++, not to tie more
closely to a C library.

I don't know how well it would work in practice. But it might be better to stick to one type for reference counting than two.

* Possibly we could have some template function utilities instead of
unsafe macros. Although I think most header files should be kept C90
compatible.


Yes existing headers that are used by the remaining C code will have to
remain C compatible, and will probably need:

#ifdef __cplusplus
extern "C" {
#endif

around them.

There's a GLib macro for that.

But (for C++ files) that doesn't prevent having extra headers with
templates in them.

Yes.

matt:
+1. While I'm also not sure it's a good idea in Geany and certainly
won't be pressing for it anytime soon, 90% of C++'s crumminess is due to
backwards compatibility with C, so I think it should be (theoretically,
not socially) possible to gradually transition from one to the other in
a project like Geany without too much pain.

colomban:
I doubt it, C++ is sufficiently different from a C program not to be
compilable by a C++ compiler in many cases -- even if it is just for
some implicit casts C++ requires to be explicit (IIRC), and there are
plenty.  Or maybe it depends what "too much pain" means:)


So long as the gain is larger than the pain.

I don't think it would be significant pain. I'm happy to be the guinea pig though.

Also, I doubt it's any kind of sensible either, because good C++ use is
sufficiently different from C to require large rewrite.  In this case,
better rewrite everything and don't keep the clumsy code

I disagree it *requires* a large rewrite. You can make *good* use of some
C++ features without having *idiomatic* use of C++. (E.g. dmd, the
reference D compiler is not written in idiomatic C++ - it doesn't use the
STL really, but it's still good code).


I agree with Nick, my experience is transitioning to C++ does not need a
big re-write just to get a compile.  You then *choose* what to re-write, to
take advantage of features to make life easier and safer.  Even I don't
advocate wholesale re-writing of random code to C++ idioms without a reason
:)

Yes, I don't want to move to C++ idioms unless there's a significant benefit, considered on a case by case basis.

I think it would be quite manageable. If we did this, I suggest just
converting one source file at a time, and only files that can benefit from
RAII and/or the more powerful type system.


Yes, so long as C compatible interfaces are available for as yet
unconverted files its fine, for example if GeanyDocument became a C++ class
appropriate headers would be needed.

I'd keep the API types (and all fundamental types) in C.

We would also need to disable some C++ features. I hoped we could do that
with g++ flags, but I've only found this so far:


I addressed the problems with this general idea above.  It will also lead
to ongoing bikesheds on what features are "allowed" and why can't Geany
progress to use more useful features and ... This is both wasteful of
community time, and destructive of community spirit, better to encourage
use of appropriate features, and where an "advanced" feature is
appropriate, then it can be used without having to remove such constraints.

IMO features should be judged by weighing usefulness vs maintainability & community skillset.

-fno-rtti (disable runtime info for object inheritance)


Hardly worth it :)

How will we keep the ABI compatible with C then? ;-)

There ought to be a way to disable mixed code and declarations, but maybe
not.


NEVER DECLARE ANYTHING UNTIL YOU HAVE A VALUE FOR IT.  :)

Agree, where practical. But Colomban doesn't like it.

I don't know if this can be enforced by g++, but I suggest we disallow
these keywords:

class


Why, its just a struct with default hiding, this just forces the use of
struct xxx { private: .... }.  The use of private members is an important
part of the ability of the compiler to protect the programmers from
themselves, and a big plus of C++, since it makes it easier to ensure that
required invariants are maintained because only listed entities can change
the members.

OK, you may be right. I thought it would make it clearer that inheritance and virtual functions are not allowed (even though they work with structs).

dynamic_cast


Agree it should *almost* never be used, and so just search for it is easy
enough.

I think inheritance + virtuals can be hard to maintain. And harder for some contributors to grok.

friend


Unless you are implying never to use private members, sometimes you *have *
to use friends.

I like private. I don't plan on using friend, but it's not so bad.

mutable


Its mostly useful for optimisations that we probably don't need ... yet :)


operator


Thats required to define the ubiquitous reference counting smart pointer,
but agree that operators should *only* be used where their semantics mirror
the standard ones. (and of course only in interfaces which are not used by
C code)

I would prefer to keep our code simple by not defining our own containers. In Geany's src, I think we should avoid it for simplicity.

throw


Agree, when we have mixed C/C++ code, throwing an exception from C++
through C can cause all the resources in the C code to leak since it
doesn't have any destructors to clean up for it.

OK.

virtual


Geany has a couple of places where a bastardised version of virtual
functions have been implemented in C, its ugly, hard to understand, and
error prone.  These cases *should* be replaced by C++ virtuals (if anyone
understands the C code enough to do it :)

I assume you refer to tagmanager. I'm not sure if TM needs to be OOP. I don't fancy rewriting it either ;-)


_______________________________________________
Devel mailing list
Devel@lists.geany.org
https://lists.geany.org/cgi-bin/mailman/listinfo/devel

Reply via email to