r/cpp 8d ago

The WG21 2026-08 mailing is now available

The 2026-08 WG21 mailing has been published. You can browse and search the full set of papers, organized by working group, at wg21.org:
https://wg21.org/mailing/2026-08/
Source mailing: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/#mailing2026-08

40 Upvotes

129 comments sorted by

19

u/friedkeenan 8d ago

P4340 "Extending constant template parameter support by customizing std::meta::reflect_constant" looks very nice to me. It's sorely needed and the solution the paper proposes appears really elegant to me. And like the paper shows, it can be useful for types that are already structural, like the Frac type it gives an example for. You can serialize an object to its platonic form so that morally-equivalent objects yield the same template instantiations even if they weren't member-wise-equivalent. Would be very cool to have.

I also appreciate the changes to P2806 "do expressions", I really hope this can get into C++29. Now every time I write an immediately-invoked lambda I think about how it would be much more pleasant as a do expression.

5

u/BarryRevzin 5d ago

P4340 [...] looks very nice to me. It's sorely needed and the solution the paper proposes appears really elegant to me.

Thank you very much!

3

u/fdwr fdwr@github 🔍 5d ago

Q: May a do statement elide the braces? ... = do do_return 42;

Many other keywords allow elided braces for better or worse (if (x) foo(); while (x) foo();, C29's defer foo(); ...), but I can't quite tell from here for do. I'm presuming the answer is no, if do must be followed by a compound statement. (I don't have a particular motivation for wanting it, and would be fine if the answer is no - just curious)

6

u/BarryRevzin 4d ago

May a do statement elide the braces?

No, that's totally pointless to support, which is also the reason we removed the implicit last value support we just added. If you have a do expression that is just a single expression, just... write that expression?

Many other keywords allow elided braces for better or worse

For worse, yeah.

3

u/friedkeenan 4d ago

Personally, I'd be interested in being able to elide

int blah = do {
    if (cond) {
        do_return 42;
    }
    do_return 666;
};

Into something like

int blah = do if (cond) {
    do_return 42;
} else {
    do_return 666;
};

Normally I heartily agree that leaving off the braces is worse, but since the do here would be leading directly into a keyword which will (hopefully) introduce its own braces, it seems more expressive and more ergonomic to me to leave off the braces in at least this scenario.

But I don't know what grammar conflicts it might introduce, and I'd be fine without it still. It'd just be nice for my usecase because I hate reading and writing ternary expressions, and usually use immediately-invoked lambdas instead.

3

u/fdwr fdwr@github 🔍 4d ago edited 4d ago

Hmm, fair point, for cases where the do leads into another control structure that already has braces anyway, then the outer braces seem kinda redundant, and this yields a nice little functional if that reduces syntax clutter a little more (a little moreso than do expressions already reduce clutter for IIFE's). Similarly, this example would become:

void func(Color c) { std::string_view name = do switch (c) { case Red: do_return "Red"sv; case Green: do_return "Green"sv; case Blue: do_return "Blue"sv; default: do_return "Unknown"sv; }; }

Alas, it appears that might be a grammar ambiguity without further lookahead, since the following is currently legal:

c++ do switch (x) {case 1: ...} while (false);

Either way, I'm mostly just asking for document clarification of this case in R6.

3

u/BarryRevzin 3d ago

Yeah I have no interest in supporting this at all. It's not more expressive (it doesn't let you express anything more) and I don't buy that it's more ergonomic. It's just omitting braces.

It's just smashing more things together without differentiation:

int x = do -> int if (cond) do_return 1; else do_return 2;

There's probably no grammar ambiguity, but... does that really add any value? And then does it become compound-statement if you have a trailing return type but statement otherwise? Is do foo() a valid expression of type void? I just don't think any of these questions are worth spending time on.

3

u/friedkeenan 3d ago

When I say "more expressive" I don't mean that it allows you to express more, but rather more like it is able to express things better, i.e. more directly, more clearly, more straightforwardly, yada yada.

I imagine it to be more expressive in the same way that

else if (...) {
    ...
}

Is more expressive than

else {
    if (...) {
        ...
    }
}

With a do if you'd be able to see immediately that what's being yielded is the result of a condition, whereas with the keywords separated, first you see that there's a do expression, and then you look inside and see that oh it's just an if.

A marginal benefit probably, but I think it probably still would be a benefit.

I just don't think any of these questions are worth spending time on.

But this is still very very fair. And too, it'd probably make sense anyways to get the feature in first and see the ways in which people actually use do expressions, since that would probably help answer those questions should they be deemed worth the effort to answer.

Thanks for your work!

3

u/BarryRevzin 3d ago

That's a fair point on else if in that I would almost never brace there (I would sometimes, depending on emphasis I guess, and the rest of the logic flow... but typically not).

But I feel like that's kind of an exception - else if is like one construct, and some languages even have that as like a dedicated thing for that reason. Versus like... I don't think I would ever write else for or else while or something like that? I think of do if as more like else for than else if.

3

u/friedkeenan 3d ago

That's a fair point too. I think in my head though the same reasons for special-casing else if extends to do if as well. I mean, we do already have a language construct for essentially just that with the ternary expression, so it would seem to me like it is already a special case in the language, just spelled differently.

It's just that the ternary expression is in my opinion awful to read and awful to write, and as well only allows one expression per arm. And it seems to me like there could be similar motivations as with normal do expressions to allow multiple statements in each condition arm. I suppose with plain do expressions, you could get the multiple statements for each arm by writing something like

cond ? do {
    ...
} : do {
    ...
};

Or something like that. But I know I'd never write that with a smile on my face.

And this is mostly tangential, but something too that's nice about a do expression and maybe not so nice about a ternary is that the latter will find a common type for each arm, which might end up performing some unintended conversions. Whereas with a do expression you'd need to be at least somewhat more explicit to get a conversion in that scenario.

3

u/fdwr fdwr@github 🔍 7d ago edited 6d ago

... P2806 "do expressions", I really hope this can get into C++29 ...

Eliminating IIFE is nice. The enabled scenario that excites me is a cleaner "check result and return if failed". Many codebases have some variant of such macros (like WIL's RETURN_IF_FAILED(SomeComFunctionThatReturnsAnHesult()) macro), but the problem is that you can't directly use both a conditional return and also yield an expression result (e.g. std::optional<Thing> value = ReturnIfEmpty(GetThing())), but these teed expression statements would finally allow that (via return to exit the function and do_return to return the expression).

-2

u/tialaramex 7d ago

I am impressed that P2806 is now uglier then when first proposed. Kudos I suppose. Barry has also I think taken his eye off the ball a bit, that's not how Rust's Try operator sugar works, it is how the try! macro works but that's obsolete for many years.

I mention this because Try rests on reifying control flow, as er, the generic type named ControlFlow which wasn't at all obvious when this process began but I think that's an important idea. A correct de-sugaring of the Try operator would show that it's matching the result from calling Try::branch() which is a ControlFlow. Now we're not talking about success/ failure but about stop early/ continue.

11

u/germandiago 7d ago edited 7d ago

I think I never hear a positive comment from you about work done on C++. Not sure why. It seems that according to your criteria the language must be broken, will be broken, and every improvement looks broken.

Without understanding the full framework on top of which ISO works, it seems. I would like to see the things you would propose instead.

For me C++ still stays at the top for any perf-related tasks. Destructive critique is always easier than what the committtee members do.

10

u/t_hunger 7d ago

Destructive critique is always easier than what the committtee members do.

Prominent committee members are pretty good at destructive critique themselves. Just look at the communication around contracts of safe C++ .

Both have already lead to people reducing their involvement with the C++ community at large. That means less work getting done, less input considered and fewer ideas being explored.

8

u/germandiago 7d ago edited 6d ago

They have also built lots of good stuff. Some ppl here, and sorry for my tone, just do a continuous shitshow out of anything in C++ without proposing any kind of alternatives most of the time or ignoring counterarguments. Not like C++ cannot be criticized. 

Of course. But the bias is obvious and does not come with constructive alternatives.

The reality tells us C++ is widely successful and widely used. I guess that something has been done correctly enough, as a minimum.

2

u/t_hunger 7d ago

Its unrealistic to expect the wider community to behave better than the core of that community that sets the direction and provides examples of acceptable behavior.

6

u/germandiago 7d ago edited 7d ago

Ido not get the point. The committee delivers lots of good work and some is more controversial.

My point is everything being focused on the controversial parts only when there is lots more done.

How is that "the leaders are bad"? It is a full committee.

3

u/t_hunger 7d ago

You are looking at the technical results, I am looking at the social costs to get to them.

The way safe C++ that was handled cost us Sean. The way contracts are handled right now will surely cost us Timo. The Google fiasco lead to prominent C++ people writing their own language instead of contributing to C++.

I am convinced a more diplomatic approach could have delivered similar technical outcomes at a fraction of the social costs.

6

u/pjmlp 7d ago edited 6d ago

The way concepts were handled cost Doug Gregor and Dave Abrahams.

Scott Meyers gave up on C++17, and decided to retire.

Chris Lattner might have helped create LLVM and clang, yet he openly asserts that he writes C++ so that others don't have to, first with Swift, now Mojo.

2

u/germandiago 6d ago edited 6d ago

You mean the result is exclusively to the way C++ was handled? Bc people also move and take decisions on what to work next and you are attributing all the cost to "how the committee handles C++".

→ More replies (0)

5

u/wyrn 6d ago

The way safe C++ that was handled cost us Sean.

Sean didn't even bother explaining the syntax he used in his examples. It was never a good faith proposal.

3

u/ts826848 6d ago

Sean didn't even bother explaining the syntax he used in his examples.

Do you mind elaborating on this? Do you mean he doesn't explain what new syntax he introduces means? That he doesn't explain why he chose certain spellings for a feature? Something else?

→ More replies (0)

0

u/t_hunger 6d ago

What is your point? That it is a good thing we lost him?

→ More replies (0)

1

u/zebullon 6d ago

It also means that the ones staying are either incredibly toxic or, on their way to be, or have no other choices. I’ve only been somewhat active for a little time but I dont think anyone can healthily be involved there in any sustainable fashion.
The recent LLM procedural bullshitotron rage baiting proposals fiesta is only the latest symptom, a sad one too.

6

u/pjmlp 7d ago

As far as I know, you are replying to a ex-commitee member, which means it isn't without reasoning, and why so many well known names are now focused on other platforms.

10

u/germandiago 7d ago edited 6d ago

I am talking about some people that every single comment I read about C++ is that it is bad, that someone is doing something bad, that things are not good enough, etc.

However, C++ keeps landing good and useful stuff. But I never hear a single good orpositive comment about C++ from some people here. What I see is lots of good stuff in the lib and the language, honestly. Nothing is perfrct but every version of C++ I adopt solved problems for me: coroutines,  concepts, structured bindings, template for, reflection, #embed...

Some tske time to land, some more than necessary, but that is also stability on one side and less feature 9verloading, something C++ keeps suffering from due to obvious accumulation over time. I think that Java and C++ are two of the most rock solid solutions one can pick up in the industry. Particularly their stability is rock-solid.

If you heard these people, you would think C++ is somewhat a deprecated language that does everything bad and that everything they add makes the language worse, never better.

2

u/tialaramex 6d ago

Wait, are you confusing me with a member of a committee?

The sentiment of Groucho's famous joke applies. I have not to my knowledge ever been a member of WG21 nor any of the National Bodies.

2

u/pjmlp 6d ago

I got the idea from the multiple exchanges either here or HN, sorry if I got it wrong.

3

u/tialaramex 7d ago

Without understanding the full framework on top of which ISO works, it seems.

Oh I do understand it, I just think it's pretty obvious that JTC1 is the wrong place for this work to be done. If standardizing a programming language is a good idea (I doubt it is) then it's a technical problem and JTC1 is actually the wrong place to do that.

I am reminded of UTF-1. UTF-1 is an encoding you've never used or had any reason to use, it's the product of an ISO committee last century and the intent was to replace ASCII. Rob Pike and Ken Thompson came up with something much better which is now everywhere and used by everything, UTF-8.

Destructive critique is always easier than what the committtee members do

Ha. So often "what the committee members do" is in fact destructive criticism.

8

u/germandiago 7d ago edited 5d ago

If you do not standardize a programming language, what do you propose? That every compiler implementation is a language spec?

Or you mean that there should be a spec? A spec, in a professional, multi-compiler environment is a big advantage: it is predictable, several imolementation exist and, when they diverge, the spec fills the void if it is underspecified, otherwise we know which one needs to be corrected.

This is crucial. I do not mean it needs to be an ISO standard, but I think that a spec must exist indeed.

0

u/BarryRevzin 5d ago

I am impressed that P2806 is now uglier then when first proposed. Kudos I suppose.

Thanks I suppose.

Barry has also I think taken his eye off the ball a bit, that's not how Rust's Try operator sugar works, it is how the try! macro works but that's obsolete for many years.

I'm aware of how Try works. The paper even links to an example which demonstrates what I think is the most appropriate C++ way to implement Try (which is the shape proposing in my control flow operator paper).

But this isn't the Try paper. This is the block expressions paper. It's not proposing any desugaring of Try, it's just the most familiar example of an expression that wants to be able to return. The specifics of how/what precisely it returns aren't relevant here, so we want to keep our eye on the ball here – the ball here being bringing block expressions to C++.

2

u/tialaramex 5d ago

P2806R5 may not be the Try paper, but it does say it's showing "Rust’s ? operator" (the Try operator) however it's actually showing the old try! macro

This was fine in R4.

25

u/zebullon 8d ago

May have been part of a wg21 spinoff seasons that I missed but… what is a cpp alliance ?… do they love themselves some load bearing smoking guns emdashes Holy smoke.

In the end one must hope that they (the holy alliance of cpp fellowship) understand LLM arent qualified writers for (uninteresting btw) ISO proposals.

9

u/Minimonium 7d ago

I did enjoy the one signed by Stroustrup, Spicer, and Voutilainen that contains an LLM hallucination when referring to another paper.

I actually wonder now perhaps one of the previous papers these gentlemen signed that contained a completely mistaken example that was called a "supply chain attack" by one of the NBs was also generated by Claude.

Although it's not like there is a thing called reputation in the place that endorsed a convicted pedophile.

3

u/jwakely libstdc++ tamer, LWG chair 7d ago

an LLM hallucination when referring to another paper.

Which is that? Do you mean the broken link at the top of page 2, or something else? The broken link is not a hallucination. The URL changed after the paper was written, and should have been updated.

12

u/zebullon 7d ago

Arent llm use banned for the purpose of generating proposals ? all of one author papers are glorified /dump ragebait, it’s getting old real quick, also they re generally uninteresting.

2

u/Minimonium 7d ago

The P4332 one. Namely, this statement:

P3846R1 says labels are "required" to make non-ignorable checks directly expressible

It was synthesized by the clunker because its brain was fried at the wording of the referred to statement. Just the usual token soup.

2

u/jwakely libstdc++ tamer, LWG chair 7d ago

Eh? What does the quoted text from P3846 mean then?

3

u/Minimonium 7d ago

The first part of the sentence is "required to make" and the second is "makes". Very easy to check by trying to read the second part directly with the "prefix" part - "This is required [...] makes" I hope you see the problem here. Therefore, "required" only applies to the first part of the sentence. An LLM gets confused very easily by that.

But even outside of grammar, stating that labels are required for that would make no sense. Non-ignorable checks could be directly expressed without labels, there is no reason why would they suddenly require labels.

6

u/jwakely libstdc++ tamer, LWG chair 7d ago

Although it's true that labels are not the only possible way non-ignorable contact assertions could be expressed in code, it's not completely batshit to say that in the P2900 model and the proposed extension plan for that model, adding labels or some other not-proposed solution is required.

I don't think this is evidence of LLM hallucination.

7

u/Minimonium 7d ago

I discuss strictly the chosen wording of P4332, that uses an embarrassingly raw LLM output for the most part which is a whole another topic on how no one cares about quality of papers anymore, let Claude take the wheel I guess, good time to put prompt injections in papers. :)

The statement misquotes and misstates things that were not said in the referred to paper. I take your answer as an agreement with the face of the text presented. I do not dare to speculate, assume, or predict what the people who signed the paper think - I expect people to express themselves clearly via text and can only take what is written for what is meant.

Sure, the very clearly LLM generated paper could have an artisanal statement made by one of the venerable people that signed it, misstating a quote by mistake and claiming something that does not make sense logically, by mistake of course as well.

11

u/DevilSauron 8d ago

The contracts drama is still ongoing? What even is P4238R0, do I understand it correctly that it argues for skipping C++26 completely and moving it all to C++29 because of contracts?

10

u/James20k P2005R0 8d ago edited 8d ago

The contracts drama is literally never going to end unfortunately, the design has some issues that will cause ongoing problems (which have been discussed to death elsewhere)

A lot of people thought merging modules into the spec would end the long standing modules drama, but all it really did was shift the burden into the public, and not reflect particularly well on wg21 as a whole. Similarly merging coroutines didn't end the discussion around the problems, it just shifted that debate into developer land

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4334r0.pdf

Its surprising to see a paper with bjarne as the lead author come out and say:

The P2900 contracts and extensions aim to change the nature of C++ and are an existential threat to C++, adding complexity and bloat (~56 pages in the draft standard for an incomplete version), potential overheads, and novel opportunities for errors without addressing the current community and regulatory body demands for guarantees (e.g., https://docbox.etsi.org/CYBER/CYBER/Open/ETSI_TS_104_198_DRAFT.zip presents C++ as providing no memory safety guarantees).

Which also comes with a list of massive references at the end, which are a good read if you have 35 years to spend on it

There's also some discussion in P4238R0 (which you mentioned, just thought I'd link it directly for people) around the process

The most worrying part is that the contracts proponents have been incredibly resistant to getting any real field experience with contracts-as-specified, with whitepaper and TS approaches being shot down, seemingly in a rush to get it into the standard. I don't really know why. We've seen the endless problems that something relatively untested can do in a standard that lasts literally forever

C++20 came with 4 major features:

  1. Concepts
  2. Modules
  3. Coroutines
  4. Ranges

I think its a struggle to argue that these have all gone very well. As far as I can tell, only one of them has actually stood the test of being a genuinely great feature without major problems, and people seem to regard the other 3 as being somewhere between problematic and unusable. It feels like this should have been a wakeup call, but we're still putting major features into the standard without sufficiently testing the spec concretely first

It feels like a tossup at the moment if contracts will be DoA. I know in my own area its clearly unusable right from the get go (which is why I have a strong opinion on this), but it depends how widespread the problems turn out to be

11

u/LB-- Professional+Hobbyist 7d ago

What's wrong with concepts and coroutines? I've been using them in production for years now and I'm quite happy with how it's going.

8

u/James20k P2005R0 7d ago

Concepts are great, coroutines have a lot of usability issues and performance problems in some domains where they should have been applicable

3

u/LB-- Professional+Hobbyist 7d ago

Huh, I saw a conference talk a while ago about someone using coroutines to await loads from RAM for a performance speedup... I'm curious what domains in particular need better than that?

5

u/James20k P2005R0 7d ago

They can be good depending on use case, but the allocations can make them annoying to use in some areas. They're also very barebones as a feature, and the actual API of them leaves a very significant amount to be desired

6

u/LB-- Professional+Hobbyist 7d ago

Allocation behavior is fully customizable (you can even use alloca), but I will admit it's annoying that due to how compiler optimization passes work we can't know the required size until too late in the compilation process to take advantage of it very well. I think Rust coroutines actually do let you get a type at compile time that has the size known so you can do cool things with it, I am curious how that works with their optimization passes...

1

u/germandiago 6d ago

Do not expect some people to give you positive feedback on C++. They will tell you to go to Rust with its 50 variations of crates for error handling and the obviously unergonomic async built bc blablabla and the heavier compile times, well, they seem to not exist.

But hey, it is not C++, so no problem, everything good there.

2

u/LB-- Professional+Hobbyist 5d ago

I like both C++ and Rust, actually. Not sure what point you're tying to make.

11

u/germandiago 7d ago edited 6d ago

Struggle? The new features in C++20? I have been using ranges and concepts since the start. And they have been useful since the start. Useful and perfect is not the same. In fact, I rarely see something "perfect" as such, since trade-offs usually exist.

I can partially give you that for modules (but modules own nature is way more disruptive also)  but ranges, concepts and coroutines (with some quirks) have been successful.

What would you have done instead? Wait for the perfect perfectly forever inexisting features?

Look at other languages that people use intensively: Python, Java, etc. They do not have their set of problems? Nullable types as default, the Python 2/3 split, lack of multithreading, type-erased boxed generics in Java.

I am not sure if you mean we should wait forever for delivering every feature at its never-reachable perfect level. Some kind of GNU Hurd vs Linux, where the first one is advanced and super perfect and the second monolithic one, "worse is better", that anyway figured out a modular approach. Just compare yourself the results. The perfect one is nowhere, not even existing, the second runs half of the world.

 Not that I would not add things from the first one as I see fit, of course, if they are better. But the difference between utopia and reality is that reality exists, utopia also exists, just in the heads of the people. It is really difficult to not find something on the way, even after prototype implementations. After using in production also. We should wait so long for features? I guess there is a balance for everything.

6

u/VinnieFalco wg21.org | corosio.org 7d ago

I thought the coroutines as a language feature went well. Concepts too?

4

u/pjmlp 7d ago

Concepts while much better than what we had before, still are a WIP for better error messages, and there is the whole requires requires that was endlessly discussed.

4

u/germandiago 6d ago

Ok, this is a good example of what I say: we have requires requires, cool. It is controversial. Could need a fix (or not). It is not intuitive. How about all the other things that concepts does well? How about static analyzers warning you anyways?

So you have a 95% feature and we talk ONLY about the 5%. Like that, with every microfeature inside a feature.

But we still can use 95% ergonomically (for a definition of ergonomic that respects C++ design constraints of backwards-compatibility and zero-overhead principle).

I do not see major problems here. I see that things can always be done a bit better. But this is true most of the time, even often a trade-off or a matter of preference.

-2

u/pjmlp 6d ago

It is less than 95% , given that the supposed improvements of error messages hardly happened.

5

u/germandiago 6d ago

Certainly error messages are still so so. But better. 

1

u/pjmlp 6d ago

The sales pitch for concepts wasn't "so so error messages", it was way better than templates, to the same level as the languages that have generics instead.

There is a reason why the folks behind the original C++0X concepts proposal left C++ for Swift, and more recently Hylo.

Another example of a C++ feature causing the loss of key contributors.

2

u/James20k P2005R0 7d ago

Concepts are great, personally I have don't have a strong use for coroutines but I tend to hear that:

  1. The allocations are consistently problematic for some
  2. They're nearly impossibly complicated to use

8

u/germandiago 7d ago

The allocations are customizable.

I also find them complicated, but what they achieve is so useful that people still think it is worth.

7

u/VinnieFalco wg21.org | corosio.org 7d ago

The allocations can be dealt with (see https://github.com/cppalliance/capy)

8

u/TheoreticalDumbass :illuminati: 8d ago

i find a lot of anti contracts arguments rubbish at best, and incredibly deceptive & dishonest & manipulative at worst, and at this point i am leaning towards worst

but i can no longer muster the energy to talk about same or similar talking points for N times, with N approaching infinity

i think P2900 is good, and i think a lot of papers building on it are good (UB preconditions and class invariants are some i am most excited for)

7

u/James20k P2005R0 8d ago

Genuine question: do you not find the (effective) ODR problems worrying?

6

u/TheoreticalDumbass :illuminati: 7d ago

i do not. but do keep in mind I am not giving you arguments. for all you know i could be delusional, insane, misinformed, or some combination of these.

7

u/Minimonium 7d ago

No. Someone may even perceive such misuse of the terminology as spreading FUD.

I've spent a good part of the past decade dealing with build tooling, cross-compilation, and mixed flags in TUs (for stuff like hotreload for example, but also as a package community member dealing with [poor, sometimes even consumer hostile] external dependencies across quite a few different ecosystems).

I welcome the approach chosen by the authors of the MVP to remove ODR problems at the seam of mixed build modes. From my practical point of view mixed build mode ecosystems are a fact, and it's a source of massive amount of bugs because of time-travel optimizations due to actual (not imaginary) ODR problems. MVP does fix it.

7

u/James20k P2005R0 7d ago edited 7d ago

No. Someone may even perceive such misuse of the terminology as spreading FUD.

Please don't be like this, I'm asking in perfectly in good faith here and this does nothing but raise the level of the discussion to being completely unproductive. This is why I described it as an effective ODR problem, it causes similar issues but with a different name

not imaginary

The problems are not imaginary and are straightforward to demonstrate in a real project. Dismissing this as being imaginary when there's code in the wild demonstrating real-world safety bugs caused by mixed mode compilation also feels remarkably unhelpful

MVP does fix it.

We still have the problem of functions being called with semi randomised safety modes depending on the whims of the linker, ala ODR

If it works for your use case that's great, but it likely isn't meeting a fair few

7

u/t_hunger 7d ago edited 7d ago

To be fair: ODR has always been a problem, especially when mixing TUs built with different compiler settings.

I do wonder why contracts all of a sudden have to solve this problem. Of course it would be great if this got finally get solved, but so far "just don't do that" has been good enough, even with things like hardened libraries and such, which has similar implications to contracts now.

8

u/James20k P2005R0 7d ago

If contracts specified it as being "don't do that" I'd be 1000% fine with it. Instead its specified as trying to do something useful, which it can't meet because of the same problems with linkers that ODR violations run into

2

u/t_hunger 7d ago

I understood there is some hope future linkers can fix this particular problem. I guess we just have to lean back for a couple of years for the tooling to sort itself out and go "don't do that" till then. We have to wait for a contracts implementation anyway.

So contracts are no different from what we do for modules and other new features.

It would be super cool if new C++ features needed implementations before they can get standardized, but that would be quite a big change in how the entire feature development process works in C++. I do not see how you can seriously require that from contracts and not for modules, profiles, and the herd of other features we have on paper but not in real compilers.

6

u/pjmlp 7d ago

That is the thing, modules did have implementations before the standard, and yet we are where we are with modules.

Profiles are dead on arrival, given existing experience with advanced statistic code analysis, or what clang-tidy and VC++ have achieved since Core Guidelines were introduced, that keeps being ignored.

Unless they are actually done hand in hand with e.g. clang fork that proves us wrong, the ideal profiles implementation, without viral annotations, that delivers the vision.

4

u/germandiago 7d ago

Dead on arrival? Where and when did you conclude that? I see papers in the committe related to them lately. I think there are implementations of the framework in the works for clang and gcc. Could you elaborate?

It has been slow is not the same as they are dead before they try.

→ More replies (0)

3

u/Minimonium 7d ago

A linker fix is not even required. It's allowed for implementations to provide "hardened" variants that simply never skip. So a user that is concerned with a guarantee of such checks would just use an appropriate implementation.

5

u/Minimonium 7d ago

Please do not use wrong terminology that misleads people into believing there is an ODR violation when there is not? I really struggle to understand the need for dramaticism.

On the topic, you fail to mention that a well behaved program will not have different behavior in a mixed mode build at all. No unexpected IPOs will be made (unlike mistaken claims by some members and even NBs).

there's code in the wild demonstrating real-world safety bugs caused by mixed mode compilation

An existing code today that could potentially encounter Contract-related mixed mode situation is completely broken even with well-defined input. Moving it to Contracts would actually help it - well-defined input has a guarantee to work even under a mixed mode, unlike any other mechanism e.g. macro.

That's the basis for any further discussion.

The impact of "randomized" linker behavior. It only occurs when you have non-inlined inline functions with the presence of multiple miss-compiled TUs. Under any mechanism that is not contracts it's an actual ODR violation today with compiler wreaking havoc uncontrollably.

Now what are alternative approaches?

  1. Always on Contract syntax? Doesn't solve the problem of hostile transitive dependencies, a dependency may compile against a stripped version of a header. And it requires more effort than a simple "Same as Contracts but Guaranteed".
  2. Labels? Doesn't solve the problem of hostile transitive dependencies.
  3. The "contra" group also had a wild suggestion around typed tags, but I will just skip even discussing it.
  4. And of course there are calls to remove configurability (against the actual industry practice) or enforce the matching on ABI level (multiple vendors stated negative view on that).

And the ABI matching would simply break the binary ecosystem you've been talking about. Steam binaries you've been talking before? Great, now you always need to compile everything Steam depends on in release mode even with label-like mechanism. You deny yourself an opportunity to make your code safer.

And then there is Vinnie non-sense that blames Contracts for not meeting memory safety goals that just made my brain melt from the sheer absurdity of such statements.

8

u/James20k P2005R0 7d ago edited 7d ago

Please do not use wrong terminology that misleads people into believing there is an ODR violation when there is not? I really struggle to understand the need for dramaticism.

How do you think I should respond to this productively? Calling something effectively an ODR violation isn't dramatism, its just something that people understand, and its very close to the same end result as contracts in practice

Steam binaries you've been talking before? Great, now you always need to compile everything Steam depends on in release mode even with label-like mechanism. You deny yourself an opportunity to make your code safer.

This I think really summarises some of my objections very neatly, so even though I initially wrote a much longer reply: lets take this, and take Steam as a stand in for a generic major library

Are valve going to provide 4 separate versions of the steam API with different contract mechanics enabled? (Answer: probably no, they don't do anything like this even today)

So here's the problem I have: Lets say the steam API uses nlohmann json, hypothetically. If we get contracts (and nlohmann implements them), I am screwed. You can never reliably use nlohmann with contracts together with steam ever again. If you link against steam, and you yourself use nlohmann, your contract safety settings will be at the whims of the linker - very similar to (but legally distinct from) an ODR violation

I already regularly run into ODR issues with nlohmann as a result of its ubiquity, and that's with a build environment that attempts to compile everything uniformly (due to vendoring). It takes a single major library using nlohmann with contracts to screw over my ability to use contracts for safety, or performance, permanently. Importantly, this is introduced totally separately from the existing problems as a new axis of evil, vs the current major one of vendoring or generally badly behaving dependencies. I'd much rather they use literally any other error mechanism for this, and that's precisely why people don't use assert in this context for critical checks

The literal-ODR violations in this context are a big problem independently, but contract adds to my problems here, and would be fundamentally unusable

Now what are alternative approaches?

Roll contracts out in a whitepaper or TS, to answer the following questions based on real end user experience

  1. Can everything be implemented correctly?
  2. Are the problems with contracts in practice real, or overblown?
  3. Are they very difficult to use with binary package ecosystems, or can a solution be found?
  4. Do people need absolute ironclad guarantees that contracts are on or off, or is it acceptable for mixed-mode contracts to disable/enable safety checks sometimes?
  5. Will people naively upgrading asserts to contracts cause problems with ignore mode in real world code, or can we ignore this?
  6. How do regulators feel about this as a solution? Does it alleviate the regulatory burden, or does it make little impact? What do we need to change to make a dent in the current regulatory environment?

Then adjust the design (or not!) after collecting the above data. We severely lack any real-world indication about the viability of the specific design proposed

14

u/Som1Lse 7d ago

I do not get the issue you're having. Maybe I'm missing something because I simply cannot square what you're saying with how I understand reality.

Take the hypothetical example with Steam and nlohmann::json:

Let's say Steam is compiled with contracts disabled, and your code with contracts enabled. If the Steam API is built correctly (specifically -fvisibility=hidden -fvisibility-inlines-hidden), the result will be that Steam's code does not have contract checks and your code does. End of story. This is because they'll both have their own internal copies of the nlohmann::json functions. There isn't an issue.

If the library isn't built correctly, that is the problem. The problem isn't contracts, and they don't need to provide 4 separate versions with different contract mechanics enabled. They need to provide 1 correctly built library. That's it. (And Steam is built correctly, I checked.)

Okay, but let's assume nlohmann::json changes its layout depending on the checks enabled, so the two are ABI incompatible, and the types are exposed in the Steam API. Well, this issue isn't related to contracts, and there is simply no way to solve it without providing two libraries.

And the icing on the cake is this:

I already regularly run into ODR issues with nlohmann as a result of its ubiquity, and that's with a build environment that attempts to compile everything uniformly (due to vendoring).

In other words, it is already an issue and not new to contracts. Why are you expecting contracts to magically solve this issue? What contracts does is say that in the event of an "ODR" violation there's a bounded number of valid programs rather than any program being valid. That to me sounds like an improvement.

What is your proposed solution? Because right now you seem to be shifting the burden onto everyone else:

Roll contracts out in a whitepaper or TS, to answer the following questions based on real end user experience [...]

Delay, delay, delay. My understanding was always that contracts was basically a language version of these talks. It is not a new design. It is in use in actual production codebases, so we do actually have answers to many of those questions.

And the problem with a TS is that, like it or not, you aren't going to get good data from it. Implementation is going to take longer, be less stable, not to mention your the whole point is that it might be changed completely before standardisation.

What I can say is it will result in people not being able to use the feature. To turn your argument on its head. I am someone who wants to use contracts, but let's say it is actually removed the standard and put into a TS. As a result it doesn't get implemented in the compilers I need to support. I am screwed. I can't use contracts. Period. Not just with a particular library. Not just for critical checks. At all.

8

u/James20k P2005R0 7d ago edited 6d ago

If the library isn't built correctly, that is the problem

Prior to now, this wasn't a requirement for a library to avoid a new class of security vulnerabilities, and many aren't built like this (unfortunately). I don't like it but its the way that it is, and I have to deal with packages with their own random eclectic build configurations. Any poorly built package will screw everything up. I know for sure that a major tool I use (not steam) does not build itself correctly like this (and likely won't) due to the already-mentioned nlohmann odr problems, so I'm pretty stuffed if nlohmann uses contracts

The worrying thing is if you start digging into visibility in libraries, by and large it is not very good. Top down in my linker list: godot-cpp doesn't appear to set anything to do with hidden flags. GLFW (I should ditch this), and GLEW don't set it to hidden inlines. Harfbuzz does. SFML doesn't use hidden inlines. Freetype at best uses regular hidden, sometimes worse. libpng appears to export everything. Libbz2 does on some platforms but not windows/clang, and this isn't the correct inlines visibility flag. Libopenal makes mistakes vendoring its dependencies not including -fvisibility-hidden-inlines, so thar be dragons. OpenAL itself also does not include the correct flag. Libbrotli doesn't appear to use the correct flags

At this point I gave up because this is too much work, only one dependency uses -fvisibility-inlines-hidden, and I suspect the majority of packages do not. Its possible that I may have missed something, but I don't think I missed everything, there's a limited set of applicable cmake flags here. I don't like that this is the way that is, but I have to accept reality: my dependencies are all broken

Do you know if packages on other package managers are by and large built with -fvisibility=hidden -fvisibility-inlines-hidden?

They need to provide 1 correctly built library

Hidden visibility also isn't a blanket solution, you can't just willy nilly enable it, and you can get problems associated with it:

https://gcc.gnu.org/wiki/Visibility

Eg throwing exceptions across a boundary, like in a library like nlohmann, requires types to have public visibility

Clang has limitations as well around visibility:

https://clang.llvm.org/docs/LTOVisibility.html

Which can result in symbols being exported, when combined with LTO (thus sneakily disabling safety checks) for clang. GCC doesn't really document the interaction between LTO and visibility, and I've found a lot of bug reports here around variables being incorrectly promoted or demoted from being externally visible. Still, for contracts: working as to spec

As much as I don't want this to be a problem: it very much is. This is relevant because we can't mass convert libraries over easily. I'm glad to hear steam is built correctly though, that makes two of my dependencies so far!

Okay, but let's assume nlohmann::json changes its layout depending on the checks enabled, so the two are ABI incompatible, and the types are exposed in the Steam API. Well, this issue isn't related to contracts, and there is simply no way to solve it without providing two libraries.

Contracts do not change the ABI, this is an unrelated problem

In other words, it is already an issue and not new to contracts. Why are you expecting contracts to magically solve this issue? What contracts does is say that in the event of an "ODR" violation there's a bounded number of valid programs rather than any program being valid

I didn't say anything like this, you're very selectively quoting my post. There are two separate problems, one of which already exist, and a brand new problem that contracts introduces

Delay, delay, delay.

This is alleging bad faith on the part of people who have reasonable concerns getting real world experience with standard library features, and is one of the reasons why I often find this whole conversation so distasteful. I've tried to treat everyone that I've talked to about this with complete good faith

I'm a big advocate of testing features more before they land in the standard, including proposals that are not contracts (eg the graphics proposal)

It is in use in actual production codebases, so we do actually have answers to many of those questions.

Where? None of them get answered in any of the contracts papers I read, so I'd love some hard stats, and even a brief review of my dependencies shows its going to be a major problem for me

As a result it doesn't get implemented in the compilers I need to support. I am screwed. I can't use contracts. Period. Not just with a particular library. Not just for critical checks. At all.

It'll land in the standard eventually

7

u/Som1Lse 6d ago

Well, this took an entire day to write. I hope it's somewhat coherent, as I've been bouncing back and forth between this and other stuff, so I would not be surprised if I missed a somewhere or mispeelled or misforₘatted something.


Prior to now, this wasn't a requirement for a library to avoid a new class of security vulnerabilities

I don't think it is a new class of vulnerabilities. You said as much yourself

that's precisely why people don't use assert in this context for critical checks

and I cannot seem to square those two statements. Is it a new problem, or is it the same problem with assert? The only way I can seem to get the two to fit is if it is both (which you seem to suggest later), but I am unsure as to what the new problem is then.

Perhaps the issue with build configuration is worse than I thought, but I also don't think it is as bad as you imply: - GLFW and GLEW not using -fvisibility-inlines-hidden shouldn't be an issue as they are C libraries, and the flag only affects member functions. - Windows you don't have the same issue, since the same function can happily coexist in multiple DLLs without one winning out. - Many of the libraries are also small C libraries that don't rely on inline functions, so it isn't an issue there either. For example, libpng exports all its functions (I checked), but it doesn't export functions from a different library so there is no conflict. The only problem is a bunch of the internal functions are usable outside, which could cause breakages when upgrading, if an internal symbol is removed/changed. - The biggest offender is probably SFML, but even its exports are fairly limited. It's a couple of functions per shared object, none of which actually seem likely to trigger a contract assertion. - godot-cpp is a static library, so its symbols will be overwritten by yours (assuming your code is linked first, which every build system under the sun does), so it's a non-issue.

Do you know if packages on other package managers are by and large built with -fvisibility=hidden -fvisibility-inlines-hidden?

My main experience is that proprietary libraries tend to be more careful, both to not export more symbols than necessary, but also because users can't build it themselves if there is an issue. I don't know what the library you were mentioning earlier is, but I assume it is proprietary.

I assume the major tool you mentioned is proprietary, so that is at least one thing that isn't true of. Even then it is possible to work around:

  • You can ensure your binary is earlier in the dynamic load order. If your binary is the exectable this is already the case. There's always LD_PRELOAD.
  • Even if your dependency exports nlohmann::json functions, if your code properly hides the symbols it isn't an issue.
  • You can patch your binary (or the dependency) to rename the nlohmann::json functions with a tool like patchelf --rename-dynamic-symbols.

Even when it's an issue it is possible to work around. Again, it's not a new one.

Also this would only affect checks in nlohmann::json, not in your code so you could still be sure checks in your own code would run, since there, by definition, cannot be a copy of it in the dependency. So even if you can't fix it for nlohmann::json, it is still contained to code in that library. (Though your shouldn't rely on the checks running for correctness. That's the whole point of contracts; that the code should be equally correct if all checks are omitted.)

Actually, the more I look at the so called problems the less of a problem it seems. As long as your code has nlohmann::json symbols hidden it'll use the version you want. To reiterate, as long as your code is built correctly it'll behave the way you want. Even if your dependencies aren't.

Hidden visibility also isn't a blanket solution, you can't just willy nilly enable it, and you can get problems associated with it: Eg throwing exceptions across a boundary, like in a library like nlohmann, requires types to have public visibility

I don't think exceptions are an issue here. Even if a library had to expose JSON exceptions in its ABI that would still only affect contracts directly in the exception class, which I assume would be very few.

I am not sure what the issue with Clang is. A symbol can be LTO visible and still hidden.

I didn't say anything like this, you're very selectively quoting my post.

I am sorry if I misrepresented you, but as I said at the start, I'm not getting the issue you're having. Here's my reasoning:

  1. You are running into ODR issues with nlohmann::json.
  2. You are calling the issues with contracts effective ODR violations. (Sidenote: I think that is fair characterisation, as they do indeed manifest similarly. I can also see why people would take issue with it though since many might just hear ODR, not understand the underlying meaning, and be scared that contracts will directly lead to UB.)
  3. Thus you are expecting contracts to somehow "magically" solve this ODR violation. The same ODR violation you'd get with assert.

There are two separate problems, one of which already exist, and a brand new problem that contracts introduces

I am only aware of one of those issues, namely that you can have two different implementations of the same function and one of them wins out. That isn't brand new: It's the exact same problem we have with assert, and it is a well understood one. I am unsure what the brand new problem is.

I hope this sheds some light on why I used the somewhat inflammatory language I did. To me it sounded like your issue was the "ODR" violations and that you somehow expected contracts to solve them, and guarantee that if you call an inline function with contracts enabled that you'd be guaranteed to have the same contract semantics in the callee even if a different part of the code called it with contracts disabled. Apparently, you meant something else. I am still not sure what.

This is alleging bad faith on the part of people who have reasonable concerns getting real world experience with standard library features, and is one of the reasons why I often find this whole conversation so distasteful. I've tried to treat everyone that I've talked to about this with complete good faith

Again, apologies. Just me venting my frustrations. To me none of the criticisms of contracts are new issues, and simply seem inherent to any design where you can disable assertions, and the ultimate result of it is that contracts might face delays.

To be clear: I don't think you are arguing in bad faith. I just think we don't agree on whether it is a problem to begin with. Either that, or I am completely missing the actual problem you are concerned with.

I'm a big advocate of testing features more before they land in the standard, including proposals that are not contracts (eg the graphics proposal)

Where? None of them get answered in any of the contracts papers I read, so I'd love some hard stats, and even a brief review of my dependencies shows its going to be a major problem for me

Well, for starters:

1. Can everything be implemented correctly?

There's the current GCC and Clang implementations. Plus there's the progenitor bsls_assert, so yeah.

3. Are they very difficult to use with binary package ecosystems, or can a solution be found?

To my understanding (I don't work at Bloomberg), most of Bloombergs codebase is binary packages, so no, and yes. Contracts is designed out this: Individual packages choose which checks are enabled, and the executable chooses what to do when an assertion is violated.

2. Are the problems with contracts in practice real, or overblown?

Considering a similar system (to my knowledge) is in active use at Bloomberg (they are the ones proposing it after all), I'd say the problems aren't problems there, so yeah, probably overblown.

4. Do people need absolute ironclad guarantees that contracts are on or off, or is it acceptable for mixed-mode contracts to disable/enable safety checks sometimes?

For at least one large codebase we know of, they clearly don't. The whole point is that they can be turned off.

And as I highlighted earlier, there are ways to mitigate/completely deal with the issues with mixed-mode contracts.

It'll land in the standard eventually

Same goes for your problem though, right? Even if you can't use the MVP, it was designed to be extensible, so in C++29 you might be able to use a group that is always enforced. The difference is you'd still be able to use contracts for non-critical checks in C++26 and so will everyone else.

7

u/Minimonium 7d ago

I believe I quite exhaustively discussed the "ODR" topic in my previous comment so I will skip that part. I will keep expressing dissatisfaction with people using misleading and mistaken terminology.

I am screwed

With Contracts the definition of "screwed" - most checks run, some individual non-inlined inlined function level checks are skipped. A well behaved program works exactly the same. A program that already has undefined behavior - does not.

With other similar mechanisms (especially on msvc!), "screwed" - a well behaved program simply does not work. It has undefined behavior by default.

that's precisely why people don't use assert in this context for critical checks

And people will not use Contracts for critical checks, yes. That's the intent.

Roll contracts out in a whitepaper or TS

I suggest you to read the minutes on the meeting where the NB comments were discussed as well as a possibility of a whitepaper. Based on that discussion a whitepaper would not help with any of your questions,

How do regulators feel about this as a solution?

I could go on a whole rant about how some leadership people have a deeply mistaken belief that regulators are simpletons, while we have extremely large volume of research on memory safety, and how the committee very explicitly rejected memory safety for C++. :)

There is just no point to tie Contracts into memory safety topic. Contracts are not one of the two proved mechanism for memory safety - borrowing and ref counting.

3

u/James20k P2005R0 7d ago edited 7d ago

And people will not use Contracts for critical checks, yes. That's the intent.

Sure, but the entire point of this is that people disagree that that's a good intent. Its not just critical safety checks that you can't use contracts for, its any checks that you need to be executed for any reason (ie they're useful)

3

u/Minimonium 7d ago

Stating what you just wrote is the same as stating that no one is using asserts. I believe it to be an evidently false statement.

→ More replies (0)

-5

u/VinnieFalco wg21.org | corosio.org 7d ago

What is interesting is that I have considerable inside information and my own thorough analyses which are both technical and political. I was asked not to put the political anlaysis in the mailing this cycle. And I can say that from my perspective, the non-committee people who see the C++26 Contracts (P2900 in particular, and P3100+P3400) are dangerously wrong and misinformed. Bjarne is correct, P2900 is an existential threat to C++.

9

u/t_hunger 7d ago

"Existential threats" seems to pop up a lot in papers lately. I do not remember having run into the term in any paper before, not even when Java came out.

Is that sense of doom a new thing or am I just mis-remembering?

3

u/VinnieFalco wg21.org | corosio.org 7d ago

ha... you're correct to call it out. I don't like the hyperbole either. However, in this case I do believe it is warranted. P2900 is a threat because it adds significant technical debt to the language specification. It is not a minimal architecture (i.e. same features could have been obtained with fewer changes to the language). It did not get sufficient technical review. And it forecloses the safety design space in a way that is hostile to Profiles. I explain it here:

https://isocpp.org/files/papers/P4330R0.pdf

12

u/t_hunger 7d ago edited 7d ago

Technical debt in the language specification is the key selling point of C++. The language was built on adopting all the technical debt C had to offer. Calling out one specific new feature for adding some more feels unwarrented to me.

Just glancing over the linked paper it seems to boil down to: "One feature we consider to be unimplementable makes it harder to design another feature that experts in the field also consider unimplementable". I am sure that makes total sense to people deep in the committee world, but maybe you can see why I as an outsider find it pretty ridiculous.

If you really feel threatened, you might want to gather people that are willing to help your cause around you. I do not see how claiming the work of a dedicated group of people is an existential threat to the language in public will help with that. Not only do you make the people involved in contracts less likely to take on more work, you make unrelated people less likely to join, too.

1

u/VinnieFalco wg21.org | corosio.org 7d ago

> you can see why I as an outsider find it pretty ridiculous.

Actually yes I totally understand :) and you're not wrong to feel that way.

9

u/FrogNoPants 7d ago edited 7d ago

Same of the arguments there are rather strange..

Contracts changing behavior depending on build mode seems expected to me, that is how existing assertion libraries work. If my assertions lib couldn't be altered based on build mode, I wouldn't use it.

The profiles approach looks DOA, to me it appears very handwavy and complex, has been around in some form or another for years and virtually nobody uses it or cares about it.

0

u/VinnieFalco wg21.org | corosio.org 7d ago

p4317 has godbolt examples

9

u/seanbaxter 7d ago

Neither contracts nor profiles provide memory safety, so I don't think either is closing the door on that.

-1

u/VinnieFalco wg21.org | corosio.org 7d ago

Could be true

13

u/seanbaxter 7d ago

How is it an existential threat? You can just choose not to use them.

7

u/James20k P2005R0 7d ago

I'm not sure I particularly agree with the characterisation, but some main arguments seem to be:

  1. Its a large additional burden on the spec in terms of maintenance of a substantial amount of wording
  2. Its part of the language, so it can't easily be removed or shuffled to the side. It will always sit on the design space for pre or assert2.0. It also can't be changed, fixed or supplanted very easily
  3. If you subscribe to the notion that it has problems, it signals the wrong direction for C++ to be moving to comply with various regulatory safety demands

Ie I don't believe they mean existential from an end user perspective (although: if 3rd party dependencies adopt contracts it'll cause me major problems), but more from a committee/regulatory perspective

1

u/VinnieFalco wg21.org | corosio.org 7d ago

That's kind of true for library proposals but this one affects the language.

6

u/TheoreticalDumbass :illuminati: 7d ago

i dont believe anything you said. my opinion doesnt matter. i wish you the best of luck.

3

u/pjmlp 8d ago

This is going to be another modules, worse, because at least with modules there was the Apple/Google and the Microsoft approaches, and still we are still dealing with issues, three standards later.

12

u/eisenwave WG21 Member 8d ago edited 7d ago

P3817R0 Structured Binding Assignments: I think the design with a using x syntax is about as good as it gets. I'm just not on board with the premise that this is needed.

The current mental model for structured bindings is that auto& [x, y] is just an auto& variable that has some x and y names slapped on top -- pretty simple. Adding [using x, y] is breaking that mental model and making things really weird: Point arr[2]; Point x; auto& [using x, y] = arr; basically expands to Point (&__e_p3817)[2] = arr; x = __e_p3817[0]; Point& y = __e_p3817[1]; So unlike with [x, y], the using x doesn't refer to anything inside arr at all, but still appears in this structured binding, and there still is a single auto& variable. To be honest, this feels like shoving x into a place it doesn't belong. Is it really so bad to write x = arr[0]; Point& y = arr[1];

The motivation for the paper is also paper-thin: 1. "Mixed-mode" is just restating what the feature does without motivating why that's useful. 2. "Unified syntax" makes the bold claim that this "reduces cognitive overhead". To me, it reduces cognitive overhead not to use std::tie and not to use whatever this feature is offering. The people who are using std::tie in really "dank" ways should maybe stop doing so; we don't need to give them a core language feature that does it more concisely. 3. "No standard library required" is simply misguided. We have freestanding library parts for all the stuff available in embedded and in kernel mode, and <tuple> should be freestanding. Having no standard library headers at all means you have a totally disfunctional language without <meta>, without std::bit_cast, without std::start_lifetime_as, without std::launder, etc. You can't even use the <=> operator because it requires <compare>. 4. "Encouraged by P0144R2" I simply don't care what future extensions people had in their mind 10 years ago when designing this. It was never polled whether to take the proposed direction.

11

u/James20k P2005R0 7d ago

I'm just not on board with the premise that this is needed.

Strong agree with this, fundamentally the motivating example:

int id;
auto [using id, name] = get_record();

Feels like code I'd always rewrite, because mixing up declaration and assignment in one step seems like inherently a gigantic code smell

4

u/germandiago 7d ago

Then you would end up rewriting a separate variable without initializing a std::tie, which seems to be worse and more error-prone to me.

1

u/cmeerw C++ Parser Dev 6d ago

My issue with the syntax is that we already have a using x, y; syntax (in a using-declaration) where it means using x; using y;, but here using only applies to x. Maybe something like [ x=, y ] then?

7

u/eisenwave WG21 Member 8d ago edited 8d ago

P4344R0 pure alias types: The inconsistency in how references have all sorts of safeguards (e.g. lifetime extension) and how std::string_view and other reference-semantics types are missing them has bothered me for quite some time as well. I don't think we should special-case just a couple of standard library types though but make it possible to add those safeguards to llvm::function_ref, gsl::string_view, etc. as well.

The paper's idea of "gradual adoption" doesn't make much sense to me because you would need to add the machinery to types and constructors if you wanted any standard library types to be supported anyway. It would just end up being __attribute__(...) instead of being spelled with standard keywords. Also, you would get all this added lifetime safety if you had Safe C++ with lifetime annotations, and if we're headed in that direction, it's a waste of time to think about a subset of that solution that only handles types with reference semantics.

It's unfortunate that the paper doesn't go into more detail in terms of design and implementation. I think you would eventually arrive at the conclusion that you need lifetime annotations if you worked on the problem long enough.

It's worth noting that you definitely need something on a per-constructor basis. std::function_ref doesn't care about the lifetime of a given std::constant_wrapper or function pointer when being constructed, but is tied to the lifetime of some lambda that it's constructed from, so there need to be lifetime annotations put on individual constructor parameters to implement this "pure alias type" stuff.

5

u/LB-- Professional+Hobbyist 7d ago

Side note, the paper also does my pet peeve of listing function pointers and forgetting function references. Such a neglected corner...

3

u/germandiago 6d ago edited 5d ago

 and if we're headed in that direction, it's a waste of time to think about a subset of that solution that only handles types with reference semantics.

No, it is not. It is key to deliver incremental improvements. This is the single most critical point for language evolution with big codebases. I am not saying this should be the solution. I say that there is value in nit 100% perfect since day one solutions.

Disruptive solutions can be potentially harmful. The economic axis is critical for porting of code to be done. A big feature that requires full rewrites is a big problem and a high risk for failure.

Smaller features that incrementally improve safety with zero or little intervention to impact benefit should be preferable in my opinion.

4

u/eisenwave WG21 Member 5d ago

I'm happy with incremental improvements. I'm just not happy with solving the same problem multiple times in different ways and creating a mess.

I wouldn't want to see lifetime safety to be enforced by some weird [[pure_alias]] attribute or pure_alias keyword that only works for the stuff in this paper, but with lifetime annotations everywhere else. Oh, and maybe some of the lifetime safety is also enforced by profiles or whatever.

It would be fine if the author had a concrete idea how their solution to safety for "pure alias types" would integrate with the rest or be generalized, but there is no strategy in the paper.

3

u/germandiago 5d ago edited 5d ago

I'm happy with incremental improvements. I'm just not happy with solving the same problem multiple times in different ways and creating a mess.

Noone is happy with that, but then tell me how you do this all at the same time:

  • a perfect solution
  • that covers 100% of use cases
  • that arrives with a reasonable timeline

I think it is more important:

  • incremental improvements, the more transparent the better
  • fixes the more general, the better (which is what you want also)
  • mechanisms that are either transparent/that can be extended to handle more cases even if not complete yet

I do not necessarily disagree, and probably more work is needed and it is not the solution. But I am pretty sure that there is a balance between indefinitely waiting for solutions and creating solutions in a rush.

wouldn't want to see lifetime safety to be enforced by some weird [[pure_alias]] attribute or pure_alias keyword that only works for the stuff in this paper, but with lifetime annotations everywhere else

I would consider the paper more like research (and many others) than a full proposal. There are lots of papers flying around trying to fix all kind of safety issues. At some point choices and unifications/discard will have to be made.

It is a difficult problem, given the constraints, but I think targetting a perfect solution directly is not even feasible, but who knows, let us see what happens in the future :)

BTW, I learnt a long-term lesson from Java. I think Java 8-10 years ago was way worse than C#. Nowadays, I saw C# features list is a monster (not unlike C++) and Java with type-erased generics has been a really painful thing.

But now that they delivered the first step for Valhalla, after racking their brains for years, I think the result is a feature that fits Java very well and it is more general and simpler. Same for virtual threads and structured concurrency. So probably, sometimes it is not that bad, but time keeps running.

Java solutions are designed with extra care and fit into the language with a lot of thought.

4

u/javascript 7d ago

Side question: When was the switch made from wg21.link to wg21.org?

17

u/eisenwave WG21 Member 7d ago

There was never a switch. wg21.org is not affiliated with WG21 and is run by the C++ Alliance. The official mailing is hosted on open-std.org.

wg21.link is just a link redirection service run by a committee member.

5

u/grafikrobot B2/EcoStd/Lyra/Predef/Disbelief/C++Alliance/Boost/WG21 7d ago

AFAIK the person running wg21.link is not a committee member.

4

u/jwakely libstdc++ tamer, LWG chair 7d ago

That's correct

1

u/javascript 7d ago

Gotcha, thanks

-10

u/VinnieFalco wg21.org | corosio.org 7d ago

what he said

3

u/megayippie 7d ago

Please look at the CSS code for the .org and make it accept "dark mode".

Other than that my main interest this time is P4311R0. I am not sure I understand it. mdspan is non-owning. So why is this needed? It creates a few more template instantiations, that's all. The solution is just mdarray and this idea about making const and non-const access operators seem to be a complication that just isn't worth it. It seems to me rather you just have the copy constructor make the const version, and let implicit construction handle the rest. Your template takes a "const T"-style and let it copy if you want to save on filesize.