Why does C++ have to break C compatibility that badly nowadays?

158 views
Skip to first unread message

Marcin Gałązka

unread,
Feb 4, 2016, 6:56:14 AM2/4/16
to std-dis...@isocpp.org
OK, I might be wrong here, many people far more experienced than me were telling I'm wrong. Nevertheless, my reasoning is as follows: Compatibility is much of a binary thing, it either exists or doesn't exist at all. You either are or are not able to compile a C program with C++. You either are or are not able to use C APIs in C++. Of course, maintaining compatibility is a burdensome thing and has lots of cons. But IMO maintaining partial compatibility is not the answer. As soon as most C programs cease being compatible with C++, you stop getting the benefits of maintaining any compatibility at all. Therefore, there seem to be only three possibilities: you can maintain compatibility and reap benefits of it while accepting the burden, you can break compatibility and get no benefits of it but also free yourselves of the burden, or you can maintain partial compatibility and get no benefits while still bearing the burden. And I'm afraid C++ chooses this third way. The list of compatibility issues seems to be slowly, but surely growing. Examples: * No VLA support. As soon as VLAs were added to C, they seem quite a natural way to declare many arrays that previously had to be allocated with malloc. Therefore, we can expect newer C code to use VLAs quite often. This is one big reason why one may be unable to painlessly transfer their C code to C++, just by compiling it with a C++ compiler and mixing in C++ features whenever convenient (and this possibility was, correct me if I'm wrong, one of the big factors of the success of C++). Since some mainstream C++ compilers support VLAs anyway, perhaps - just perhaps - adding it to the standard wouldn't be that problematic? * No support of the register keyword. This keyword is likely to be used in headers. Therefore, this might create compatibility issues in one of the most important fields: the ability to use C APIs by #including C headers. Again, since some mainstream compilers support it anyway, perhaps adding it to the standard would be acceptable. * No support of bounds-checked functions. The issue here is similar to that of VLAs: their use seems natural in C, so one may fail to be able to compile existing C code by a C++ compiler. * The tendencies to drop support of c-strings by streams, http://cplusplus.github.io/LWG/lwg-active.html#2499 . I sure was ranting on this list that operator>> can be used like gets and that's bad; but! I was hoping to enforce setting the width, not to deprecate or remove this overload at all! If this overload gets removed, one may have to resort to cin.getline to be able to read words, which is counter-intuitive. If cin.getline also got removed, one would have to either resort to cstdio to read to cstring (which may interact badly with iostream facilities used elsewhere), or to read into a std::string created especially for this purpose and then copy it's contents into the target cstring (which is redundant). Please do not drop the support of cstrings by streams! To sum up, in my opinion, C++ should choose one of two alternative paths: either maintain compatibility with C to greatest possible extend, or drop it radically by gradually deprecating and removing facilities inherited from C, that are considered 'evil' in C++. The latter option will give many opportunities to clean up the language. The former will give the benefits listed above. Trying to balance between these two extremes offers benefits of neither of these options, but drawbacks of both.

David Krauss

unread,
Feb 4, 2016, 10:45:29 AM2/4/16
to std-dis...@isocpp.org
On 2016–02–04, at 7:56 PM, Marcin Gałązka <marc...@hotmail.com> wrote:

* No support of the register keyword. This keyword is likely to be used in headers. Therefore, this might create compatibility issues in one of the most important fields: the ability to use C APIs by #including C headers. Again, since some mainstream compilers support it anyway, perhaps adding it to the standard would be acceptable.

register is being removed from the next version of the standard because it does nothing. A conforming compiler up to C++14 or C11 must ignore it in function prototypes. This is because a function declaration without register is valid for linkage to a definition using register.

Out of curiosity, on what platform are you seeing breakage?

* No support of bounds-checked functions. The issue here is similar to that of VLAs: their use seems natural in C, so one may fail to be able to compile existing C code by a C++ compiler.

This is an optional part of the C library. If the C headers have it, it will be available in C++ too. The optional features in C11 create compatibility issues, but that’s not for C++ to solve.

For the related upcoming core language feature, see the various papers on contracts.

Marcin Gałązka

unread,
Feb 4, 2016, 11:20:22 AM2/4/16
to std-dis...@isocpp.org
> register is being removed from the next version of the standard because it does nothing. A conforming compiler up to C++14 or C11 must ignore it in function prototypes. This is because a function declaration without register is valid for linkage to a definition using register.

I'm sorry. For some weird reason I was thinking 'restrict' and I typed 'register'.

Thiago Macieira

unread,
Feb 4, 2016, 5:27:00 PM2/4/16
to std-dis...@isocpp.org
On quinta-feira, 4 de fevereiro de 2016 11:56:11 PST Marcin Gałązka wrote:
> Of course, maintaining compatibility is a burdensome thing and has lots of
> cons. But IMO maintaining partial compatibility is not the answer. As soon
> as most C programs cease being compatible with C++, you stop getting the
> benefits of maintaining any compatibility at all. Therefore, there seem to
> be only three possibilities: you can maintain compatibility and reap
> benefits of it while accepting the burden, you can break compatibility and
> get no benefits of it but also free yourselves of the burden, or you can
> maintain partial compatibility and get no benefits while still bearing the
> burden. And I'm afraid C++ chooses this third way.

The problem is that the C standard is developed independently from the C++
standard. That means the members of WG14 are allowed to add features that
don't make sense in C++, duplicate C++ features or are simply incompatible
with C++ syntax.

If you were to ask them to always talk to WG21 before adding features, you'll
probably get the same reaction as you're getting here, though.

The people most interested in compatibility are the compiler writers, though.
You should be able to find supporters with them.

> * No VLA support. As soon as VLAs were added to C, they seem quite a natural
> way to declare many arrays that previously had to be allocated with malloc.
> Therefore, we can expect newer C code to use VLAs quite often. This is one
> big reason why one may be unable to painlessly transfer their C code to
> C++, just by compiling it with a C++ compiler and mixing in C++ features
> whenever convenient (and this possibility was, correct me if I'm wrong, one
> of the big factors of the success of C++). Since some mainstream C++
> compilers support VLAs anyway, perhaps - just perhaps - adding it to the
> standard wouldn't be that problematic?

VLAs were briefly added to C++14 drafts, at least the parts of them that were
sane. They were removed later because of issues. So you should consult the
list of issues to see why the C++ standards committee decided this should not
be added. Hopefully, those will be fixed so we can have some VLAs in C++ code
-- they're useful.

In addition to the issues, there were aspects of VLAs that the committee felt
were duplicating functionality existing in C++, namely that of template
container classes. We have a solution for passing arrays across function
calls, we don't need VLAs for that.

> * No support of the register keyword. This keyword is likely to be used in
> headers. Therefore, this might create compatibility issues in one of the
> most important fields: the ability to use C APIs by #including C headers.
> Again, since some mainstream compilers support it anyway, perhaps adding it
> to the standard would be acceptable.

I understand you meant restrict here, not register.

I've also been told there were issues with this, but I have no recollection of
what they are. Maybe something related with classes with members.

> * No support of bounds-checked functions. The issue here is similar to that
> of VLAs: their use seems natural in C, so one may fail to be able to
> compile existing C code by a C++ compiler.

Because we have template container classes, which do the bounds checking.
Duplicated functionality is not needed and the C++ standards committee feels
that if something can be solved by a library, it should be solved by a library
not a core language change.

Maybe C should stop adding those features that C++ has already solved. If they
aren't willing to add templates (not _Generic), they should maybe simply not
add the feature at all. _Atomic and _Complex come to mind too.

I imagine this would not be a popular proposal among WG14 people.

> To sum up, in my opinion, C++ should choose one of two alternative paths:
> either maintain compatibility with C to greatest possible extend, or drop
> it radically by gradually deprecating and removing facilities inherited
> from C, that are considered 'evil' in C++. The latter option will give many
> opportunities to clean up the language. The former will give the benefits
> listed above. Trying to balance between these two extremes offers benefits
> of neither of these options, but drawbacks of both.

Bjarne Stroustrup posted a paper once about the incompatibilities and where/
how they hurt. You should look it up and read it. Most of your concerns are
listed there.

That said, I don't expect any solution of this short of developing both
languages in lockstep.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center

Brian Bi

unread,
Feb 4, 2016, 5:47:25 PM2/4/16
to std-dis...@isocpp.org
On Thu, Feb 4, 2016 at 3:56 AM, Marcin Gałązka <marc...@hotmail.com> wrote:
OK, I might be wrong here, many people far more experienced than me were telling I'm wrong. Nevertheless, my reasoning is as follows: Compatibility is much of a binary thing, it either exists or doesn't exist at all. You either are or are not able to compile a C program with C++.

This is one big reason why one may be unable to painlessly transfer their C code to C++, just by compiling it with a C++ compiler and mixing in C++ features whenever convenient (and this possibility was, correct me if I'm wrong, one of the big factors of the success of C++).  

Is this even one of the design goals of modern C++? If you wanted to migrate from C to C++, you've had more than 25 years to do it. Would you write a new C program today, use features like VLAs, and then expect it to work with a C++ compiler?

To sum up, in my opinion, C++ should choose one of two alternative paths: either maintain compatibility with C to greatest possible extend, or drop it radically by gradually deprecating and removing facilities inherited from C, that are considered 'evil' in C++. The latter option will give many opportunities to clean up the language. The former will give the benefits listed above. Trying to balance between these two extremes offers benefits of neither of these options, but drawbacks of both.

C compatibility is not the only reason to retain "evil" features. It's also for backward compatibility with earlier dialects of C++.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.



--
Brian Bi
Reply all
Reply to author
Forward
0 new messages