C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Possible clean API break solution

From: Marcin Jaczewski <marcinjaczewski86_at_[hidden]>
Date: Thu, 1 Sep 2022 00:00:09 +0200
śr., 31 sie 2022 o 13:30 Thiago Macieira via Std-Proposals
<std-proposals_at_[hidden]> napisał(a):
>
> On Tuesday, 30 August 2022 20:44:27 -03 Marcin Jaczewski via Std-Proposals
> wrote:
> > I think yes, even more I think whole C++ success was built on breakage
> > like this.
> > ABI break I am referring to is compatibility with C. C++ makes a break
> > from it by adding
> > mangling to allow linking safely with old C code without confusion.
>
> Indeed, but C++ was never meant to be the same language as C.
>
> What you're proposing is effectively a new language, one that may call into the
> old one but not be called from it. With all the pitfalls that may turn up if
> you abuse #ifdef __cplusplus or forget it.
>

More a new version/flavor of C++, it could be in some way compared to
the "epoch" proposal
but is more fine grained as you can specify each class for what
version it belongs to.

I do not think that `#ifdef` will be a problem, as any error will have
clear link error as each version has a distinct
mangled name.

I would see problem more in that:
```
extern "C++20"
{
   std::string a;
}

extern "C++30"
{
   std::string b;
}

static_assert(!std::is_same_v <decltype(a), decltype(b)>);
```
but this is targeted for header libraries and experts where most
people will not need to bother with this.

> > extern "C++20" struct A
> > {
> > std::_30::string x; //newer version of string for some improvements
> > std::_20::vector<bool> y; //our favorite version of current vector :>
> > };
> >
> > inline A Create(const std::string& x) //current `string` based on
> > compiler option
> > {
> > return A{ x }; //implicit constructor from other version of `string`
> > }
>
> > And this code could be included in the header and work exactly
> > the same in all available versions of C++.
>
> I'm ok with that as written, because you have to opt-in to the new types. Or,
> phrased differently, std::string is the same old and never something that is
> binary-incompatible, and it's std::_30::string that must have a constructor to
> copy or move from the old std::string. That comment on Create talking about
> compiler options is wrong or misleading, since there's no compiler option that
> would change which std::string gets used.
>

`std::_30::string` and `std::_20::string` are two diffrent types. With
completely different name mangling.
`std::string` is one of these two based on what context of `extern
"???"` is used.

Standard too could make some generic explicit constructors that could
be used to transfer data between
version of string, something like:

```
template<StdString S> //concept that only allow diffrent versions of
`std::string`
explicit base_string(const S& s);
```

It should be only a copy constructor as for move operation we would
need too much assumptions about how each version works.

And what version is `std::string` is controlled by the compiler as you
can now choose `-std=c++20` or `-std=c++23`.
Code NEED to behave differently and have different `std::string`
otherwise compiling old versions will be impossible.
My idea is more of an escape hatch that allows you to locally change
the version you want to link with.
This will need a new compiler to compile everything or at least to
prepare only specific objects files that could be correctly linked
in the old compiler.


> > //using MyTypeError = MyType; //error: name is ambiguous
> > using MyTypeOld = extern "C++20" MyType;
> > using MyTypeNew = extern "C++" MyType;
>
> Obviously this doesn't compile as C++20 today, so you're going to need #ifdef
> around it.

Yes, for current compilers it would need `#ifdef` but this use case
will happen in C++23 or C++26
where you have some code that worked for C++20 but needs to be
compiled in C++23 standard or C++30.
Or you link pre C++20 object files to your code from C++26.

This code will be compiled by new compiler:
```
extern "C" {
#incldue "veryOldLib.h" //this is pure C lib
}
extern "C++20" {
#include "someOldLib.hpp" //this lib work only in C++20 and was not
updated to use this feature
}
extern "C++23" {
#include "lessOldLib.hpp"
}
```


>
> > This will allow for big codebases to "freeze" some old parts to old
> > versions of C++ but still allow new compilers and new improvements in
> > other parts of code while still mixing both flavors.
> > cost of "freeze" of some headers will be same as writing C/C++ headers
> > that work for both languages:
> >
> > ```
> > #if __cplusplus > 202002L
> > extern "C++20" {
> > #endif
> >
> > //...
> >
> > #if __cplusplus > 202002L
> > } // extern "C++20"
> > #endif
>
> This doesn't look correct. Either you meant extern "C++" or the ... should be
> inside the #if too.

Example is correct, this is for C++ code that needs work now and
should have linkage like C++20 even when compiled in C++26 or newer
version.


I would see rolling out this break would take two standard versions,
first would introduce all these new features that are required for it
to work.
Next version will make breaking changes by bumping name mangling.

Another thing if we already have some control over mangling then why
not allow some thing like `extern "C++VS"` or `extern "C++GCC"` as
extension.
This would improve portability between different compilers.

> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel DCAI Cloud Engineering
>
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2022-08-31 22:00:21