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.

Comments below.

Cheers
Lex


On 27 August 2013 01:07, Nick Treleaven <nick.treleaven@btinternet.com> wrote:
From the C99 discussion:

lex:
>>> Unless we follow the example of gcc itself and upgrade to C++ :)

me:
>> Not sure that's a good idea for Geany now, although I'm glad that gcc
>> did it. They use a restricted subset IIRC. I miss templates and RAII in
>> C though.

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.  Since the runtime costs are still there, all you have saved is the cost of the pointer in the object (or at least reduced it to a flag indicating the object type, but then you have to test it each use, again error prone).

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 :).
 

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
 

* 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

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.
 

* 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.
 

* Possibly we might use some STL containers internally.


Most definitely.

 
* 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.
 

* 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.

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

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.
 
>
> 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 :) 
 

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.
 

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.
 

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

Hardly worth it :)
 

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.  :)

For those having trouble finding declarations not at the top of a scope, remember Geany highlights types, so declarations stand out, just change your theme to make them more visible Colomban ;)
 

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.
 
dynamic_cast

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

Unless you are implying never to use private members, sometimes you *have * to use friends.
 
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)
 
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.
 
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 :)
 

That could be enforced with a 'make check' build target.

Thoughts?

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