Interim draft 2 of D0762R0: Concerns about expected<T, E> from the Boost.Outcome peer review

170 views
Skip to first unread message

Niall Douglas

unread,
Oct 3, 2017, 4:51:33 PM10/3/17
to ISO C++ Standard - Future Proposals
Dear all,

Firstly thank you so much for such detailed responses on draft 1 of D0762R0 in the other discussion thread. But I'm getting very concerned that you're discussing material which is no longer in D0762R0 because some of your fellow WG21 members recommended by private email that I drop that material.

I don't want to waste anyone's time, so I attach an interim edition of draft 2 which will be the paper being sent to WG21 shortly. I strongly must stress that this is literally a dump from my editor and is quite literally half finished. But you'll find most of the problematic stuff has been removed, the argument has been greatly simplified and made more directed, ambiguities have been removed or clarified.

Feedback is absolutely welcome on this interim draft 2 edition. Of those WG21 members which have already seen it, they say it is a great improvement over draft 1 and draft 0, it merges the best parts of both previous attempts.

But I am absolutely open to hearing any problems you find with this paper.

I'm currently putting the children to bed, I will respond to the other thread when I can.

Niall

wg21_outcome_review_20171003_.pdf

Niall Douglas

unread,
Oct 3, 2017, 10:24:43 PM10/3/17
to ISO C++ Standard - Future Proposals
Please find attached the finished D0762R0 paper.

Feedback is very much welcomed on this paper.

I'll turn my attention to the operator try proposing paper tomorrow night and try and get it done by end of week. Right now it's 3.23 am, I am going to bed!

Niall
wg21_outcome_review_draft2_final.pdf

Vicente J. Botet Escriba

unread,
Oct 4, 2017, 3:34:29 AM10/4/17
to std-pr...@isocpp.org, Niall Douglas
Hi Niall,

I don't think you have interpreted well the Boost review. The next
review will say.


Similarities
3. Having the same name is not enough. expected return by reference and
error is narrow.

6. I don't see what you mean for " type sugar for wrapping a T or an E
to give it unambiguous convertibility". If it is about unexpected(e),
there is no syntactic sugar for T.

Disimilarities

1.Right.  I'm all for explicit constructors. I would prefer to have
construction from expected(e) and unexpected(u). This was not retained
by LEWG.
If we believe implicit conversion from E is preferable we could change
expected.
IMHO, this is not a major point to justify a new class (in the
standard). We need to decide what we want.

2.  All this is just a naming difference. Both provide narrow and wide
access contracts. We can spend as much time as we want bike-shedding.
3. This part of 2.
IMHO, this is not a major point to justify a new class.

4. I requested you to give examples on why expected couldn't have
[[nodiscard]] attribute.
IMHO, this could be a major point to justify a new class.

5. I'm all for been explicit and it is useful to have types that are not
default constructible. LEWG requested to maintain default construction
if T is default constructible.
IMHO, this is not a major point to justify a new class.

6. As other said, what prevents expected to propagate standard layout?
This could be a major point to justify a new class, if we don't know how
to do it for expected.

7. We could have it in expected if really needed.
IMHO, not a major point to justify a new class.

8. As I said to you , this is not true. Please point from where you have
this and we will fix it.

9. I proposed a solution with a expected<T, void> which was not
accepted. Other possibilities as success/failure can be adapted to expecte.
IMHO, not a major point to justify a new class.

10. As I said to you I like explicitness.
IMHO, not a major point to justify a new class.

Sorry for all the IMHO, this is not a major point to justify a new class
I mean in the standard, of course.


2.1 whenever we want it can be adopted for expected. Not a major point
to justify a new class.

2.2 What prevent implementation of expected to use a struct based when
the types T, E are trivial. Could this be seen as a QoI?

2.3 I recognize that I have not addressed this point, but what prevent
expected to preserve it?

2.4 How checked<success<T>, failure<E>> would behave?

3 Conclusion
You lost me here. Are you saying that value should be narrow now?

The 2 major points are for me are [[nodiscard]] and propagation of T/E
properties.
If expected<T?E> can not provide them, then this could justify a new
class or even the removal of expected.

The other are as always up to use to decide. The standard doesn't
provides all possible designs.

Best,
Vicente

Barry Revzin

unread,
Oct 4, 2017, 9:42:31 AM10/4/17
to ISO C++ Standard - Future Proposals
I don't understand what this paper is actually proposing. Are you suggesting changes to the expected proposal? If so, what? 

Or are you proposing new types for the standard library? The names checked<T,E>, unchecked<T,E>, and result<T,E> (and result<T>?) are used but it's not clear from the paper what those actually are. If so, it would help to see what the interfaces of these types are and their intended usages. 

Nicol Bolas

unread,
Oct 4, 2017, 10:44:39 AM10/4/17
to ISO C++ Standard - Future Proposals


On Wednesday, October 4, 2017 at 9:42:31 AM UTC-4, Barry Revzin wrote:


On Tuesday, October 3, 2017 at 9:24:43 PM UTC-5, Niall Douglas wrote:
Please find attached the finished D0762R0 paper.

Feedback is very much welcomed on this paper.

I'll turn my attention to the operator try proposing paper tomorrow night and try and get it done by end of week. Right now it's 3.23 am, I am going to bed!

Niall

I don't understand what this paper is actually proposing. Are you suggesting changes to the expected proposal? If so, what? 

No, he wants `result` either in addition to or instead of `expected`. Essentially, he considers it fine to have both and fine to have `result`, but not fine to have just `expected`.
 

Niall Douglas

unread,
Oct 4, 2017, 5:18:42 PM10/4/17
to ISO C++ Standard - Future Proposals

I don't understand what this paper is actually proposing. Are you suggesting changes to the expected proposal? If so, what? 

No, he wants `result` either in addition to or instead of `expected`. Essentially, he considers it fine to have both and fine to have `result`, but not fine to have just `expected`.
 

No, that's an earlier draft now discarded.

It's now a list of recommendations for changes to the expected proposal.

Niall

Ville Voutilainen

unread,
Oct 4, 2017, 5:21:08 PM10/4/17
to ISO C++ Standard - Future Proposals
Does it have the full synopsis/interface and description of semantics
thereof, or are we just supposed to parse
it together from a list of recommendations?

Niall Douglas

unread,
Oct 4, 2017, 5:37:32 PM10/4/17
to ISO C++ Standard - Future Proposals, nialldo...@gmail.com
I don't think you have interpreted well the Boost review. The next
review will say.

I do say this is possible in my introduction. But equally Vicente there was a fair bit of pointed criticism against Expected's design during that peer review which you felt was wrong, and so you ignored it. Not dissimilarly, if I felt an item of peer review was wrong, I ignored it too. I think we are equally as guilty on this.

We'll find out by the end of this year in any case.
 

2.  All this is just a naming difference. Both provide narrow and wide
access contracts. We can spend as much time as we want bike-shedding.

Sure, technically this is "just a naming difference". But that's exactly at the heart of the problem. I do go into some detail on my argument in this in section 2.1 "All wide or all narrow observers". I think Optional is wrong, and so is Expected for copying it. Names and naming matter.
 

4. I requested you to give examples on why expected couldn't have
[[nodiscard]] attribute.
IMHO, this could be a major point to justify a new class.

And as I replied to you, without some ability to inspect types for whether they have that attribute or not, it's a tricky thing for Expected due to its unfocused design remit.

As section 2.4 "Self disabling implicit constructors" points out, Outcome has a more focused design remit. That makes possible for it, things not possible for Expected.
 

5. I'm all for been explicit and it is useful to have types that are not
default constructible. LEWG requested to maintain default construction
if T is default constructible.
IMHO, this is not a major point to justify a new class.

I'm not sure where you're getting this "justify a new class" from. You told me by private email that that was not possible, so I have dropped that request entirely from this paper. As per your feedback.

This paper is now exclusively about summarising the design differences and making recommendations for changes to Expected.
 

6. As other said, what prevents expected to propagate standard layout?
This could be a major point to justify a new class, if we don't know how
to do it for expected.

This is discussed in section 2.3 "Standard layout propagation"
 

8. As I said to you , this is not true. Please point from where you have
this and we will fix it.

The paper says "Checked requires type E to be default constructible". Note the "Checked".
 

2.2 What prevent implementation of expected to use a struct based when
the types T, E are trivial. Could this be seen as a QoI?

Discussed literally in the paper, with options discussed and a recommendation made.
 

2.3 I recognize that I have not addressed this point, but what prevent
expected to preserve it?

Discussed literally in the paper, with options discussed and a recommendation made.
 

2.4 How checked<success<T>, failure<E>> would behave?

I believe the use of clarifying type sugar in checked<T, E> is disallowed, and will not compile.
 

3 Conclusion
You lost me here. Are you saying that value should be narrow now?

Yes. Remove all throwing behaviours and bad_expected_access entirely. Makes Expected simpler. If users want it to throw exceptions, they can very easily inherit Expected and tack that on.

I also recommend struct-based storage, not union-based storage. And that to be written into the spec. Again, Expected becomes simpler, and much easier for the compiler to compile the many hundreds of operations using Expected per compiland.

And finally I recommend that standard layout-ness be propagated. Those are the three recommendations I am making. I fully expect WG21 to ignore me, but I will live better in the future knowing that I tried to change things before it was too late.

Niall

Niall Douglas

unread,
Oct 4, 2017, 5:40:56 PM10/4/17
to ISO C++ Standard - Future Proposals

> It's now a list of recommendations for changes to the expected proposal.


Does it have the full synopsis/interface and description of semantics
thereof, or are we just supposed to parse
it together from a list of recommendations?

I have rewritten this paper entirely three times now. What you see now is what you're getting, bar fixed errata.

Make of it whatever you choose. I entirely expect it to be completely ignored. I submit this paper because I believe the Expected proposal is suboptimal and I will sleep better in the future once it's standardised knowing that I tried to change things. That's all.

Niall

Ville Voutilainen

unread,
Oct 4, 2017, 5:43:05 PM10/4/17
to ISO C++ Standard - Future Proposals
There might be a better chance of changing things if it's easier to
compare the full class synopses.
I realize you've already spent excessive amounts of energy on this
proposal, but I have no qualms about
asking for more, if/when it's important.

Niall Douglas

unread,
Oct 4, 2017, 6:02:54 PM10/4/17
to ISO C++ Standard - Future Proposals
>> > It's now a list of recommendations for changes to the expected proposal.


There might be a better chance of changing things if it's easier to
compare the full class synopses.

The three recommendations are pretty straightforward:

(i) all narrow observers, remove bad_expected_access entirely. Simpler.

(ii) Require struct-based storage, prohibit union-based storage. Even simpler.

(iii) Propagate standard layout-ness of T and E. I even gave a suggested layout.
 
I realize you've already spent excessive amounts of energy on this
proposal, but I have no qualms about
asking for more, if/when it's important.

You can ask of course, but next I've got a tutorial to write for Outcome and a talk on Expected to write for Meeting C++. And I really, really hate writing these papers, I especially hate standardese. I already have nightmares about proposing AFIO for standardisation next year as the first step in implementing STL2.

Niall

Nevin Liber

unread,
Oct 4, 2017, 6:18:46 PM10/4/17
to std-pr...@isocpp.org
On Wed, Oct 4, 2017 at 5:02 PM, Niall Douglas <nialldo...@gmail.com> wrote:
(ii) Require struct-based storage, prohibit union-based storage. Even simpler.

What exactly does that have to do with a proposal for a type in the standard?  That seems like a QoI detail.  If it isn't, then what behavior does it change?
--
 Nevin ":-)" Liber  <mailto:ne...@eviloverlord.com>  +1-847-691-1404

Tony V E

unread,
Oct 4, 2017, 6:34:36 PM10/4/17
to Standard Proposals
On Wed, Oct 4, 2017 at 5:43 PM, Ville Voutilainen <ville.vo...@gmail.com> wrote:
On 5 October 2017 at 00:40, Niall Douglas <nialldo...@gmail.com> wrote:
>>
>> > It's now a list of recommendations for changes to the expected proposal.
>>
>>
>> Does it have the full synopsis/interface and description of semantics
>> thereof, or are we just supposed to parse
>> it together from a list of recommendations?
>
>
> I have rewritten this paper entirely three times now. What you see now is
> what you're getting, bar fixed errata.
>
> Make of it whatever you choose. I entirely expect it to be completely
> ignored. I submit this paper because I believe the Expected proposal is
> suboptimal and I will sleep better in the future once it's standardised
> knowing that I tried to change things. That's all.

There might be a better chance of changing things if it's easier to
compare the full class synopses.

And/or a table.  Before vs After.

I think we also need a table for some of the design choices of expected/result/outcome/etc.
Basically a "menu" of choices that we can build from.
(As long as that doesn't turn into a design-by-committee mess.  Not all the choices in the table would be independent from other choices.)

But I know that's a lot of work.

I realize you've already spent excessive amounts of energy on this
proposal, but I have no qualms about
asking for more, if/when it's important.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUbmVYhbK_dy-196kSVUkcbZaUt6GKjXg89SV-MX8K8JsQ%40mail.gmail.com.



--
Be seeing you,
Tony

Niall Douglas

unread,
Oct 4, 2017, 6:36:27 PM10/4/17
to ISO C++ Standard - Future Proposals

(ii) Require struct-based storage, prohibit union-based storage. Even simpler.

What exactly does that have to do with a proposal for a type in the standard?  That seems like a QoI detail.  If it isn't, then what behavior does it change?

A lot of these comments would be answered if people just read the paper. But to answer your question, I discuss the pros and cons of struct-based vs union-based storage for Expected and my experience of the compile time impacts of both on large and/or complex codebases.

The Expected proposal doesn't specify one way or another like most things in the C++ standard. But most people assume a union-based storage would be the most appropriate from reading the text. I'm saying from having deployed these objects into real world code, no it really isn't.

We've seen what happens if the standard is too easy on implementation details - std::deque is a classic example, on some implementations it's super fast, on others it's so slow as to make a mockery of portable programming. This is one of those situations in my opinion: a footnote in the standard encouraging implementors to use struct-based storage may be plenty sufficient.

Niall

Niall Douglas

unread,
Oct 4, 2017, 6:48:21 PM10/4/17
to ISO C++ Standard - Future Proposals

There might be a better chance of changing things if it's easier to
compare the full class synopses.

And/or a table.  Before vs After.

I think we also need a table for some of the design choices of expected/result/outcome/etc.
Basically a "menu" of choices that we can build from.
(As long as that doesn't turn into a design-by-committee mess.  Not all the choices in the table would be independent from other choices.)

But I know that's a lot of work.

I also think it's inappropriate given that Boost haven't done their peer review of my v2 Outcome design yet.

They may completely reject it after all, or recommend significant changes as condition for acceptance.

After a peer review, and if they accept v2 Outcome, then it might become appropriate to submit tables of design choices. But I think that likely unnecessary. Vicente and indeed you will no doubt participate in a second review like you did with the first, and may bring back from that various changed opinions, like from the first review. So I think any second Boost review will do the job anyway.

Niall

Vicente J. Botet Escriba

unread,
Oct 5, 2017, 3:08:33 AM10/5/17
to std-pr...@isocpp.org, Niall Douglas
Le 04/10/2017 à 23:37, Niall Douglas a écrit :
 

2.  All this is just a naming difference. Both provide narrow and wide
access contracts. We can spend as much time as we want bike-shedding.

Sure, technically this is "just a naming difference". But that's exactly at the heart of the problem. I do go into some detail on my argument in this in section 2.1 "All wide or all narrow observers". I think Optional is wrong, and so is Expected for copying it. Names and naming matter.
We can change this from expected. I believe the committee needs a paper with good a motivation, not just that optional was wrong and we should avoir this error again. We need something more factual.

 

4. I requested you to give examples on why expected couldn't have
[[nodiscard]] attribute.
IMHO, this could be a major point to justify a new class.

And as I replied to you, without some ability to inspect types for whether they have that attribute or not, it's a tricky thing for Expected due to its unfocused design remit.
I'm lost. For me [nodiscard]] is associated to a functions. What am I missing?


As section 2.4 "Self disabling implicit constructors" points out, Outcome has a more focused design remit. That makes possible for it, things not possible for Expected.
 

5. I'm all for been explicit and it is useful to have types that are not
default constructible. LEWG requested to maintain default construction
if T is default constructible.
IMHO, this is not a major point to justify a new class.

I'm not sure where you're getting this "justify a new class" from. You told me by private email that that was not possible,
What was not possible?

so I have dropped that request entirely from this paper. As per your feedback.

This paper is now exclusively about summarising the design differences and making recommendations for changes to Expected.
In this case this was not clear to me. I suggest to remove anything that distracts the reader, as the Boost.Revirew Outcome, result, checked, unchecked ....
No need to compare the similarities and disimilarities woth something else. Just state clearly what you are against, explain why and propose something better.
A lot of people will not know what is your intent while reading  the paper.

 

6. As other said, what prevents expected to propagate standard layout?
This could be a major point to justify a new class, if we don't know how
to do it for expected.

This is discussed in section 2.3 "Standard layout propagation"
Ok, so you are proposing that optional<T> and expected<T,E> propagate standard layout. I guess variant will be in the same packet.

 

8. As I said to you , this is not true. Please point from where you have
this and we will fix it.

The paper says "Checked requires type E to be default constructible". Note the "Checked".
Oh, I see it now. So you want, expected to require that T is default constructible?
Could you tell us why this is better?

 

2.2 What prevent implementation of expected to use a struct based when
the types T, E are trivial. Could this be seen as a QoI?

Discussed literally in the paper, with options discussed and a recommendation made.
Ok, so with the current wording an implementation could use a struct based layout. But this is not enough to you. You want to force a specific layout and not a QoI.
I'm not for adding this constraint to expected, other could agree with you. The standard doesn't dictate a layout of the implementation data members. It is only as if.
This could be a major reason to have a different class. The question1st is if the committee wants this feature for expected.
 

2.3 I recognize that I have not addressed this point, but what prevent
expected to preserve it?

Discussed literally in the paper, with options discussed and a recommendation made.
So expected could propagate standard layout. The question is if the committee want this to happen for expected.

 

 

3 Conclusion
You lost me here. Are you saying that value should be narrow now?

Yes. Remove all throwing behaviours and bad_expected_access entirely. Makes Expected simpler. If users want it to throw exceptions, they can very easily inherit Expected and tack that on.
Please be more explicit on your paper. Add a specific section for removing bad_expected_access, ....
Why are you against having such functionality in expected, aside the name?

I will not be against removing value() that throw bad_expected_access if we have already something else that provide the same kind of behavior. I want a simple way to throw if there is no value. There are a lot of alternatives. My draft paper on ValueOrError types explores some of them. One thing at a time.

I will not be against removing value_or() neither with the same conditions.

I also recommend struct-based storage, not union-based storage. And that to be written into the spec. Again, Expected becomes simpler, and much easier for the compiler to compile the many hundreds of operations using Expected per compiland.
The standard can have a note that could recommend the use of struct-based storage for some types.
Recommending is not mandating.


And finally I recommend that standard layout-ness be propagated. Those are the three recommendations I am making. I fully expect WG21 to ignore me, but I will live better in the future knowing that I tried to change things before it was too late.
I believe that the committee is ready to discuss this 3 points (or even more if you had). Your paper should concentrate on these 3 points and remove anything else. Even if the paper is short it is distracting.
If you are not proposing a change, there is no need to signal a difference with respect your Outcome library.

This was my position i give to you for the first draft. Better to concentrate on the major differences that justify a change (or a new class) and let the minor things for another round.

Vicente

Jens Maurer

unread,
Oct 5, 2017, 3:37:31 AM10/5/17
to std-pr...@isocpp.org
On 10/05/2017 09:08 AM, Vicente J. Botet Escriba wrote:
>> And as I replied to you, without some ability to inspect types for whether they have that attribute or not, it's a tricky thing for Expected due to its unfocused design remit.
> I'm lost. For me [nodiscard]] is associated to a functions. What am I missing?

[[nodiscard]] can be applied to a function, indicating that its return
value should not be ignored.

[[nodiscard]] can also be applied to a class type, meaning that any
function returning that class type is implicitly [[nodiscard]].

See 10.6.7 [dcl.attr.nodiscard].

I believe the idea is that std::result / std::expected should
have the [[nodiscard]] attribute, because when such classes are
used as a function return type (carrying an error indication E),
it's a bad idea to ignore it. (That's so nice about exceptions:
It's hard to ignore them.)

Jens

Nicol Bolas

unread,
Oct 5, 2017, 11:36:06 AM10/5/17
to ISO C++ Standard - Future Proposals
OK, let's look into this point by point:

2.1 All-wide or all-narrow observers:

I don't agree with your argument that a type should pick a particular method of observers. However, let's ignore that and focus on your suggested resolution.

As noted, the standard already has a convention on observers: narrow observers use operators, while wide observers use words. Therefore, if a type is going to provide only narrow observers, it should not use words whenever possible. That is, if `expected` is not going to provide wide observers, it should not have `.value` at all.

To do so creates confusion with `std::optional::value`'s contract.

Furthermore, having `value(expected)` have different behavior from `expected::value` is very confusing. Such an ADL function feels very much like a member operation. So if there is an `expected::value`, users will expect `value(expected)` to do the same thing.

If `value` is going to behave identically to `operator*/->`, then it shouldn't exist.

2.2 Struct-based rather than Union-based storage:

This is simply out-of-bounds for the specification. Even as an implementation notation, it's just outside the scope of what the standard committee does.

If you believe that implementations will be better off using struct-based storage, then you should go to the implementers and convince them to incorporate your ideas.

Also, it's not clear how "all struct" storage could even work. `T` is not required to be default constructible, nor should it. So how could you actually have a `T` in the `expected` in the event of an error? You'd have to wrap it in some type that is default constructible, which uses dynamic storage duration for the actual `T` and forwards the copy/move operations to its contained `T` when it is engaged appropriate. That requires writing all of that code you don't want to write.

2.3 Standard layout propagation:

It's important to understand that, despite the title of this section, you're talking about two very different things. The first as indicated by the title is having `expected<T, E>` be standard layout if T and E are standard layout. This would guarantee layout compatibility for things like the common-initial-sequence rules for unions and the like.

The second thing is explicitly defining what that layout shall be. You have to understand that this is a very different step from the above. The standards committee balked at giving a type as simple as `string_view` a well-defined layout (`const char*, std::size_t`). If they're unwilling to do it for a trivial type like that, they're certainly not going to for this.

Furthermore, your goal seems wrongheaded. You cite interoperability as a reason to do this, but the only way that can happen is if there are a bunch of C APIs that start taking/returning structs like this:

typedef struct WhoCares
{
 
ActualType t;
 
ErrorCode e;
 
TypeEquivalentToBool b;
} RealName;

I am not an expert on C APIs by any stretch, but I have never seen a C API that returned a struct anything like that. Your example is artificial because you control both the source and the destination APIs, so you could just as easily have created a C-style API that marshalls the `expected` properly.

I find it odd that you argue that narrow contracts are OK because we have static analysis tools, yet you ignore the fact that those same tools (or tools based on their ideas) can also be used to generate C/C++ marshalling code very easily. If my build process already includes static analysis, why not also include static code generation?

But I digress. Most instances of C/C++ interop, in my experience, are for C APIs that were primarily intended to be consumed by other C code. Most C APIs that return both an error code and an optional value use an output parameter, and the error code is the return value. The boolean is simply one of the states of the error code. Indeed, even for C APIs that return structs of value/error code, they don't include a boolean. The error code is always a valid value; you have to test the code to see if it indicates an actual error state.

So how exactly will making `expected` standard layout improve compatibility with C? Do you really expect to see a rash of C libraries adopting structs that are compatible with it?

This is in fact why I'm not annoyed by `string_view` not having a specific layout. Because C APIs don't use that layout anyway, nor will they do so just because we standardized one.

Lastly, the thing that makes it most difficult to use code written in C++ outside of C++ is the lack of a standard ABI. Making `expected` layout compatible changes none of the fundamental ABI issues that make interoperability difficult.


 

Niall Douglas

unread,
Oct 5, 2017, 1:07:41 PM10/5/17
to ISO C++ Standard - Future Proposals, nialldo...@gmail.com

We can change this from expected. I believe the committee needs a paper with good a motivation, not just that optional was wrong and we should avoir this error again. We need something more factual.

I gave my rationale in the paper. It's about not being anti-social to end users: not adding to their cognitive load, not mish-mashing contracts into the same object, not burdening end users with having to think about exception safety.

I appreciate that all of these arguments make no sense to WG21 members. But you've got to remember you're all in the top 1% of C++ developers. You get this stuff. The average programmer does not, and curses all of you at WG21 for not thinking of what it's like at the coal face.

You then get significant C++ users banning all use of the STL in their major code bases precisely because of the anti-social-ness problem.
 

I'm not sure where you're getting this "justify a new class" from. You told me by private email that that was not possible,
What was not possible?

More than one Expected-like object in the standard.
 
so I have dropped that request entirely from this paper. As per your feedback.

This paper is now exclusively about summarising the design differences and making recommendations for changes to Expected.
In this case this was not clear to me. I suggest to remove anything that distracts the reader, as the Boost.Revirew Outcome, result, checked, unchecked ....
No need to compare the similarities and disimilarities woth something else. Just state clearly what you are against, explain why and propose something better.
A lot of people will not know what is your intent while reading  the paper.

Do bear in mind Vicente that you've seen both previous editions, and that biased you. This paper shouldn't cause the same confusion, assuming they read the first page where it explicitly states what the paper is about (FYI draft 3 which you haven't seen strengthens the "what this paper is" in the intro).

Regarding comparing Outcome and Expected, I appreciate that you personally find that superfluous. But your colleagues do not. I've had more than half a dozen direct requests to publish an exact list of similarities and dissimilarities between post-Boost-review Outcome and present Expected. Indeed even on this thread, there have been calls for more detail on the design differences, not less.
 
 

6. As other said, what prevents expected to propagate standard layout?
This could be a major point to justify a new class, if we don't know how
to do it for expected.

This is discussed in section 2.3 "Standard layout propagation"
Ok, so you are proposing that optional<T> and expected<T,E> propagate standard layout. I guess variant will be in the same packet.

Ship has probably sailed on that too, but I'd like to hope that std2::variant<> will get that right one day so C can speak Variant.
 

Oh, I see it now. So you want, expected to require that T is default constructible?
Could you tell us why this is better?

If you look more closely you'll see the flags permit neither T nor E to exist in the memory set aside for them.
 
 

2.2 What prevent implementation of expected to use a struct based when
the types T, E are trivial. Could this be seen as a QoI?

Discussed literally in the paper, with options discussed and a recommendation made.
Ok, so with the current wording an implementation could use a struct based layout. But this is not enough to you. You want to force a specific layout and not a QoI.
I'm not for adding this constraint to expected, other could agree with you. The standard doesn't dictate a layout of the implementation data members. It is only as if.
This could be a major reason to have a different class. The question1st is if the committee wants this feature for expected.

I personally think WG21's historical attitude to good relations with other programming languages has been abysmal. No other programming language out there works well with C++, which is quite frankly shocking, and entirely the fault of WG21.

And moreover it's highly damaging to the long term sustainability of the C++ ecosystem. The most galling thing of all is that even little minor improvements in specification detail would deliver outsize improvements. There really ought to be a WG21 study group dedicated to deeply integrating C++ and Python together. It would do wonders for our long term job prospects, and force the rest of WG21 to think about other people.
 

Yes. Remove all throwing behaviours and bad_expected_access entirely. Makes Expected simpler. If users want it to throw exceptions, they can very easily inherit Expected and tack that on.
Please be more explicit on your paper. Add a specific section for removing bad_expected_access, ....
Why are you against having such functionality in expected, aside the name?

I explained in the paper multiple reasons. I repeated them above. Most importantly of all, UB detection tooling is so much better today than it used to be. Just because we used to have runtime checking observers does not mean they are wise today when they eliminate the usefulness of static and runtime correctness analysis. That is a huge cost and loss, and one totally unnecessary. If the programmer really wants potential exception throwing, it is trivial for them to add it in themselves. So don't build it into the standard! It's unnecessary!
 

I will not be against removing value() that throw bad_expected_access if we have already something else that provide the same kind of behavior. I want a simple way to throw if there is no value. There are a lot of alternatives. My draft paper on ValueOrError types explores some of them. One thing at a time.

As I suggested in my paper, an external mechanism like a free function observer interface which throws exceptions is fine by me. Your draft paper also is fine with me in principle. I'm arguing against the builtin assumption of it being wise that new objects added to C++ should ever throw an exception for a logic error. I think technological improvement has made that design choice unwise and suboptimal.
 

I believe that the committee is ready to discuss this 3 points (or even more if you had). Your paper should concentrate on these 3 points and remove anything else. Even if the paper is short it is distracting.
If you are not proposing a change, there is no need to signal a difference with respect your Outcome library.

This was my position i give to you for the first draft. Better to concentrate on the major differences that justify a change (or a new class) and let the minor things for another round.

I've reduced considerably the "ask" of the paper, partially in thanks to your feedback.

But other feedback wanted more detail on the design differences and why. You might remember the very first paper I wrote was just a long list of design differences and why. That's gone now, this third rewrite I think makes everyone giving feedback equally unhappy, which sounds about right to me. 

Niall

Niall Douglas

unread,
Oct 5, 2017, 1:26:52 PM10/5/17
to ISO C++ Standard - Future Proposals

As noted, the standard already has a convention on observers: narrow observers use operators, while wide observers use words. Therefore, if a type is going to provide only narrow observers, it should not use words whenever possible. That is, if `expected` is not going to provide wide observers, it should not have `.value` at all.

That's fine, except there are not enough punctuation operators available. Expected makes .error() narrow for example. Me personally I'd have everything all narrow or everything all wide unless the name prefix says otherwise.
 

To do so creates confusion with `std::optional::value`'s contract.

The simple solution there is for Expected to drop operator* and operator-> and exclusively use narrow error and value.

Just because Optional got it wrong doesn't mean all new additions have to.
 

Furthermore, having `value(expected)` have different behavior from `expected::value` is very confusing. Such an ADL function feels very much like a member operation. So if there is an `expected::value`, users will expect `value(expected)` to do the same thing.

It was just a suggestion. Vicente's got a paper which implements a more generic and nicer solution which in my opinion (not his) even more strongly suggests that the vocab types themselves ought to be all narrow for simplicity.
 

If `value` is going to behave identically to `operator*/->`, then it shouldn't exist.

Agreed. Drop operator* and operator->. Those are for dereferencing. Neither Optional nor Expected is a pointer nor an iterator.
 

This is simply out-of-bounds for the specification. Even as an implementation notation, it's just outside the scope of what the standard committee does.

The committee chooses its scope. It can change its mind.
 

If you believe that implementations will be better off using struct-based storage, then you should go to the implementers and convince them to incorporate your ideas.

Also, it's not clear how "all struct" storage could even work. `T` is not required to be default constructible, nor should it. So how could you actually have a `T` in the `expected` in the event of an error? You'd have to wrap it in some type that is default constructible, which uses dynamic storage duration for the actual `T` and forwards the copy/move operations to its contained `T` when it is engaged appropriate. That requires writing all of that code you don't want to write.

You're overthinking it. If you never access it, uninitialised storage for a T is legal.
 

It's important to understand that, despite the title of this section, you're talking about two very different things. The first as indicated by the title is having `expected<T, E>` be standard layout if T and E are standard layout. This would guarantee layout compatibility for things like the common-initial-sequence rules for unions and the like.

The second thing is explicitly defining what that layout shall be. You have to understand that this is a very different step from the above. The standards committee balked at giving a type as simple as `string_view` a well-defined layout (`const char*, std::size_t`). If they're unwilling to do it for a trivial type like that, they're certainly not going to for this.

I am very aware that my pleas will be ignored. I am aware of what happened with string_view, which was the wrong decision. Had it been guaranteed that layout (I'd actually have chosen { const char *, const char * }) with standard layoutness, all C speaking code could now speak string_view which would have been such a boon for interoperation, particularly as C strings are so inefficient and unsafe.

If I had had the power, indeed I've have taken string_view to WG14 (C programming language) and started the process of standardising its C form over there. Big gain for them too.
 

Furthermore, your goal seems wrongheaded. You cite interoperability as a reason to do this, but the only way that can happen is if there are a bunch of C APIs that start taking/returning structs like this:

typedef struct WhoCares
{
 
ActualType t;
 
ErrorCode e;
 
TypeEquivalentToBool b;
} RealName;

I am not an expert on C APIs by any stretch, but I have never seen a C API that returned a struct anything like that. Your example is artificial because you control both the source and the destination APIs, so you could just as easily have created a C-style API that marshalls the `expected` properly.

Well of course, C++ is a superset of C. You have to restrict your use of C++ to what C can understand.

BTW here is the C API for Outcome: https://github.com/ned14/outcome/blob/master/include/outcome/result.h. We even use a fancy new C11 generic in there :)
 

I find it odd that you argue that narrow contracts are OK because we have static analysis tools, yet you ignore the fact that those same tools (or tools based on their ideas) can also be used to generate C/C++ marshalling code very easily. If my build process already includes static analysis, why not also include static code generation? 

But I digress. Most instances of C/C++ interop, in my experience, are for C APIs that were primarily intended to be consumed by other C code. Most C APIs that return both an error code and an optional value use an output parameter, and the error code is the return value. The boolean is simply one of the states of the error code. Indeed, even for C APIs that return structs of value/error code, they don't include a boolean. The error code is always a valid value; you have to test the code to see if it indicates an actual error state.

So how exactly will making `expected` standard layout improve compatibility with C? Do you really expect to see a rash of C libraries adopting structs that are compatible with it?

If WG21 made life just a little bit easier on C++ programmers needing to provide C compatibility so Python et al can reuse their code, I don't doubt you'd see a large uptick in usage.

Hell Rust has better support for foreign language interop than C++ does. And it's new.
 

This is in fact why I'm not annoyed by `string_view` not having a specific layout. Because C APIs don't use that layout anyway, nor will they do so just because we standardized one.

I view it as an awful missed opportunity. C hasn't standardised an alternative to the null terminated char array due to lack of a standardised approach to adopt. C++ setting a direction would give C the excuse to choose one over the others. Very unfortunate.
 

Lastly, the thing that makes it most difficult to use code written in C++ outside of C++ is the lack of a standard ABI. Making `expected` layout compatible changes none of the fundamental ABI issues that make interoperability difficult.

On that we certainly agree. I did a ton of R&D on solving this permanently for C++ some years ago. US$1.5m would solve it we ballparked. Still, little things which cost nobody here or at the STL vendors much can deliver outsize benefits to the C++ ecosystem. Just need to grasp that nettle.

Niall

Vicente J. Botet Escriba

unread,
Oct 5, 2017, 1:41:13 PM10/5/17
to std-pr...@isocpp.org, Niall Douglas
Le 05/10/2017 à 19:07, Niall Douglas a écrit :

We can change this from expected. I believe the committee needs a paper with good a motivation, not just that optional was wrong and we should avoir this error again. We need something more factual.

I gave my rationale in the paper. It's about not being anti-social to end users: not adding to their cognitive load, not mish-mashing contracts into the same object, not burdening end users with having to think about exception safety.

I appreciate that all of these arguments make no sense to WG21 members. But you've got to remember you're all in the top 1% of C++ developers. You get this stuff. The average programmer does not, and curses all of you at WG21 for not thinking of what it's like at the coal face.

 I don't know for WG21, but for me this is not enough.

You then get significant C++ users banning all use of the STL in their major code bases precisely because of the anti-social-ness problem.
Sorry, I cannot talk in name of all the other C++ developers.

 

I'm not sure where you're getting this "justify a new class" from. You told me by private email that that was not possible,
What was not possible?

More than one Expected-like object in the standard.
In my opinion it will be more difficult that having only one. Nothing is impossible.

 
so I have dropped that request entirely from this paper. As per your feedback.

This paper is now exclusively about summarising the design differences and making recommendations for changes to Expected.
In this case this was not clear to me. I suggest to remove anything that distracts the reader, as the Boost.Revirew Outcome, result, checked, unchecked ....
No need to compare the similarities and disimilarities woth something else. Just state clearly what you are against, explain why and propose something better.
A lot of people will not know what is your intent while reading  the paper.

Do bear in mind Vicente that you've seen both previous editions, and that biased you. This paper shouldn't cause the same confusion, assuming they read the first page where it explicitly states what the paper is about (FYI draft 3 which you haven't seen strengthens the "what this paper is" in the intro).
Great :)


Regarding comparing Outcome and Expected, I appreciate that you personally find that superfluous. But your colleagues do not. I've had more than half a dozen direct requests to publish an exact list of similarities and dissimilarities between post-Boost-review Outcome and present Expected. Indeed even on this thread, there have been calls for more detail on the design differences, not less.
 
If you don't want to propose an new class I don't see the need. If you want to propose a new class this is a must. Each sentendce has a context.
I believe people were asking for more as your are talking about things you don't define, but maybe I'm wrong.

 

6. As other said, what prevents expected to propagate standard layout?
This could be a major point to justify a new class, if we don't know how
to do it for expected.

This is discussed in section 2.3 "Standard layout propagation"
Ok, so you are proposing that optional<T> and expected<T,E> propagate standard layout. I guess variant will be in the same packet.

Ship has probably sailed on that too, but I'd like to hope that std2::variant<> will get that right one day so C can speak Variant.
 

Oh, I see it now. So you want, expected to require that T is default constructible?
Could you tell us why this is better?

If you look more closely you'll see the flags permit neither T nor E to exist in the memory set aside for them.
Please, could you clarify?

 
 

2.2 What prevent implementation of expected to use a struct based when
the types T, E are trivial. Could this be seen as a QoI?

Discussed literally in the paper, with options discussed and a recommendation made.
Ok, so with the current wording an implementation could use a struct based layout. But this is not enough to you. You want to force a specific layout and not a QoI.
I'm not for adding this constraint to expected, other could agree with you. The standard doesn't dictate a layout of the implementation data members. It is only as if.
This could be a major reason to have a different class. The question1st is if the committee wants this feature for expected.

I personally think WG21's historical attitude to good relations with other programming languages has been abysmal. No other programming language out there works well with C++, which is quite frankly shocking, and entirely the fault of WG21.
Is this specific to expected?


And moreover it's highly damaging to the long term sustainability of the C++ ecosystem. The most galling thing of all is that even little minor improvements in specification detail would deliver outsize improvements. There really ought to be a WG21 study group dedicated to deeply integrating C++ and Python together. It would do wonders for our long term job prospects, and force the rest of WG21 to think about other people.
Out of the scope of the expected proposal ;-)

 

Yes. Remove all throwing behaviours and bad_expected_access entirely. Makes Expected simpler. If users want it to throw exceptions, they can very easily inherit Expected and tack that on.
Please be more explicit on your paper. Add a specific section for removing bad_expected_access, ....
Why are you against having such functionality in expected, aside the name?

I explained in the paper multiple reasons. I repeated them above. Most importantly of all, UB detection tooling is so much better today than it used to be. Just because we used to have runtime checking observers does not mean they are wise today when they eliminate the usefulness of static and runtime correctness analysis. That is a huge cost and loss, and one totally unnecessary. If the programmer really wants potential exception throwing, it is trivial for them to add it in themselves. So don't build it into the standard! It's unnecessary!
But this is exactly the goal of the value function. to provide a simple way to thro-w an exception when there is no value. I can admit that we could have a non-member function. But the need is there.

 

I will not be against removing value() that throw bad_expected_access if we have already something else that provide the same kind of behavior. I want a simple way to throw if there is no value. There are a lot of alternatives. My draft paper on ValueOrError types explores some of them. One thing at a time.

As I suggested in my paper, an external mechanism like a free function observer interface which throws exceptions is fine by me. Your draft paper also is fine with me in principle. I'm arguing against the builtin assumption of it being wise that new objects added to C++ should ever throw an exception for a logic error. I think technological improvement has made that design choice unwise and suboptimal.
I will not be so drastic.

 

I believe that the committee is ready to discuss this 3 points (or even more if you had). Your paper should concentrate on these 3 points and remove anything else. Even if the paper is short it is distracting.
If you are not proposing a change, there is no need to signal a difference with respect your Outcome library.

This was my position i give to you for the first draft. Better to concentrate on the major differences that justify a change (or a new class) and let the minor things for another round.

I've reduced considerably the "ask" of the paper, partially in thanks to your feedback.

But other feedback wanted more detail on the design differences and why. You might remember the very first paper I wrote was just a long list of design differences and why. That's gone now, this third rewrite I think makes everyone giving feedback equally unhappy, which sounds about right to me.
No major problem.

Vicente

Nicol Bolas

unread,
Oct 5, 2017, 4:54:23 PM10/5/17
to ISO C++ Standard - Future Proposals
On Thursday, October 5, 2017 at 1:26:52 PM UTC-4, Niall Douglas wrote:

As noted, the standard already has a convention on observers: narrow observers use operators, while wide observers use words. Therefore, if a type is going to provide only narrow observers, it should not use words whenever possible. That is, if `expected` is not going to provide wide observers, it should not have `.value` at all.

That's fine, except there are not enough punctuation operators available. Expected makes .error() narrow for example. Me personally I'd have everything all narrow or everything all wide unless the name prefix says otherwise.
 
To do so creates confusion with `std::optional::value`'s contract.

The simple solution there is for Expected to drop operator* and operator-> and exclusively use narrow error and value.

But... that doesn't solve the problem. The problem being that `optional::value` has a wide contract, so users will expect `expected::value` to have one too.

Just because Optional got it wrong doesn't mean all new additions have to.

But if `optional` didn't get it wrong, then all new additions should adhere to its conventions. Your argument is approaching the level of a tautology.

Furthermore, having `value(expected)` have different behavior from `expected::value` is very confusing. Such an ADL function feels very much like a member operation. So if there is an `expected::value`, users will expect `value(expected)` to do the same thing.

It was just a suggestion. Vicente's got a paper which implements a more generic and nicer solution which in my opinion (not his) even more strongly suggests that the vocab types themselves ought to be all narrow for simplicity.
 

If `value` is going to behave identically to `operator*/->`, then it shouldn't exist.

Agreed. Drop operator* and operator->. Those are for dereferencing. Neither Optional nor Expected is a pointer nor an iterator.

Sure. And while we're at it, let's get rid of `vector::operator[]`, since `vector` is not an array. Or `function::operator()`, since `function` is not a function. And so forth.

This is simply out-of-bounds for the specification. Even as an implementation notation, it's just outside the scope of what the standard committee does.

The committee chooses its scope.

No, it doesn't. ISO publishes specifications. Specifications don't specify implementations. The entire purpose of a specification is to allow multiple implementations.

If we wanted to canonize one implementation (the way most languages do. There is no Python or Lua specification; CPython and LuaLib decide what the "standard" is, and everyone who makes their own has to implement their quirks), we wouldn't have an ISO standardization committee at all. There would just be whomever it is that owns the repo that is considered the "standard".
 
It can change its mind.
If you believe that implementations will be better off using struct-based storage, then you should go to the implementers and convince them to incorporate your ideas.

Also, it's not clear how "all struct" storage could even work. `T` is not required to be default constructible, nor should it. So how could you actually have a `T` in the `expected` in the event of an error? You'd have to wrap it in some type that is default constructible, which uses dynamic storage duration for the actual `T` and forwards the copy/move operations to its contained `T` when it is engaged appropriate. That requires writing all of that code you don't want to write.

You're overthinking it. If you never access it, uninitialised storage for a T is legal.

So, you're thinking:

struct Data
{
  alignas
(T) unsigned char[sizeof(T)] bits;
  E error
;
};

Well, that doesn't do what you want either; `Data` is not layout-compatible with `pair<T, E>`. Layout compatibility is not based on any dynamic storage duration objects; it's based on the actual definitions of the subobjects in the struct. So it doesn't matter what you stick inside `Data::bits`; as far as [class.mem]/20 is concerned, that object is only compatible with an equally aligned byte array of equal size.

I submit that there is no legal way to implement `expected` such that:

1. It is constructible from just a value of type `E`.

2. Does not require that `T` is default constructible.

3. Shares a common initial sequence with `pair<T, E>`.

The above definition fails with #3. Show me an implementation that succeeds at all three.

Now yes, as a standard library type, it's allowed to rely on implementation-dependent behavior. So we could declare by fiat that these will be true, and it's up to the compiler/library writers to work out how to make that possible. But wallpapering over things like this should only be done for really important things.

And this "feature" of `expected` is not important enough to warrant it.

It's important to understand that, despite the title of this section, you're talking about two very different things. The first as indicated by the title is having `expected<T, E>` be standard layout if T and E are standard layout. This would guarantee layout compatibility for things like the common-initial-sequence rules for unions and the like.

The second thing is explicitly defining what that layout shall be. You have to understand that this is a very different step from the above. The standards committee balked at giving a type as simple as `string_view` a well-defined layout (`const char*, std::size_t`). If they're unwilling to do it for a trivial type like that, they're certainly not going to for this.

I am very aware that my pleas will be ignored. I am aware of what happened with string_view, which was the wrong decision. Had it been guaranteed that layout (I'd actually have chosen { const char *, const char * }) with standard layoutness, all C speaking code could now speak string_view which would have been such a boon for interoperation, particularly as C strings are so inefficient and unsafe.

If I had had the power, indeed I've have taken string_view to WG14 (C programming language) and started the process of standardising its C form over there. Big gain for them too.

... how, exactly would that be a "big gain for them too"? How would completely rewriting millions of lines of code help them in any way?

Furthermore, your goal seems wrongheaded. You cite interoperability as a reason to do this, but the only way that can happen is if there are a bunch of C APIs that start taking/returning structs like this:

typedef struct WhoCares
{
 
ActualType t;
 
ErrorCode e;
 
TypeEquivalentToBool b;
} RealName;

I am not an expert on C APIs by any stretch, but I have never seen a C API that returned a struct anything like that. Your example is artificial because you control both the source and the destination APIs, so you could just as easily have created a C-style API that marshalls the `expected` properly.

Well of course, C++ is a superset of C. You have to restrict your use of C++ to what C can understand.

BTW here is the C API for Outcome: https://github.com/ned14/outcome/blob/master/include/outcome/result.h. We even use a fancy new C11 generic in there :)

Which no existing C APIs will use. Which no existing C APIs will be upgraded to. And therefore, which little future C APIs will use either.

So... how exactly does this improve C/C++ interop again? It would only be helpful for people who have C programmers on staff, writing internal C APIs that are written against such types. It would not be used by the wider C community, so it would in no way affect C/C++ interop issues. And since it won't be used by the wider community, it would be easy enough to just have those "C programmers on staff" just invent their own layout-compatible types.

And let's not forget; if this were a desirable outcome, we would already have it by now. It is within the power of every C API to return a struct containing a pair of pointers or a pointer+size or whatever. It is within the power of every C API to take such a struct as a parameter.

And yet they don't. Is this because there isn't one in the standard library? No; it's because they don't want to.

I find it odd that you argue that narrow contracts are OK because we have static analysis tools, yet you ignore the fact that those same tools (or tools based on their ideas) can also be used to generate C/C++ marshalling code very easily. If my build process already includes static analysis, why not also include static code generation? 

But I digress. Most instances of C/C++ interop, in my experience, are for C APIs that were primarily intended to be consumed by other C code. Most C APIs that return both an error code and an optional value use an output parameter, and the error code is the return value. The boolean is simply one of the states of the error code. Indeed, even for C APIs that return structs of value/error code, they don't include a boolean. The error code is always a valid value; you have to test the code to see if it indicates an actual error state.

So how exactly will making `expected` standard layout improve compatibility with C? Do you really expect to see a rash of C libraries adopting structs that are compatible with it?

If WG21 made life just a little bit easier on C++ programmers needing to provide C compatibility so Python et al can reuse their code, I don't doubt you'd see a large uptick in usage.

Well, I do doubt it, and you have provided no actual evidence for your statement.

Hell Rust has better support for foreign language interop than C++ does. And it's new.

Hey, maybe being "new" has something to do with that. Maybe having dictatorial control over implementations has something to do with that. Maybe not being a standard has something to do with that.

This is in fact why I'm not annoyed by `string_view` not having a specific layout. Because C APIs don't use that layout anyway, nor will they do so just because we standardized one.

I view it as an awful missed opportunity. C hasn't standardised an alternative to the null terminated char array due to lack of a standardised approach to adopt.

No, they haven't standardized one because they know it will not be significantly used.

C++ setting a direction would give C the excuse to choose one over the others. Very unfortunate.
 
Lastly, the thing that makes it most difficult to use code written in C++ outside of C++ is the lack of a standard ABI. Making `expected` layout compatible changes none of the fundamental ABI issues that make interoperability difficult.

On that we certainly agree. I did a ton of R&D on solving this permanently for C++ some years ago. US$1.5m would solve it we ballparked. Still, little things which cost nobody here or at the STL vendors much

Except that it does cost much. It makes my `expected` types bigger. And therefore, it makes any type that contains an `expected` bigger. Any type that intends to transport an `expected` will be bigger (`promise/future`). And so forth.

can deliver outsize benefits to the C++ ecosystem.

Because you're not fixing the ABI problem, you still need to use your code-generation tricks for interop. So you've gained nothing by providing such a guarantee; you still need marshalling code to deal with the ABI issues.

Nicol Bolas

unread,
Oct 5, 2017, 5:24:42 PM10/5/17
to ISO C++ Standard - Future Proposals, nialldo...@gmail.com
On Thursday, October 5, 2017 at 1:07:41 PM UTC-4, Niall Douglas wrote:
>
>
>> We can change this from expected. I believe the committee needs a paper
>> with good a motivation, not just that optional was wrong and we should
>> avoir this error again. We need something more factual.
>>
>
> I gave my rationale in the paper. It's about not being anti-social to end
> users: not adding to their cognitive load, not mish-mashing contracts into
> the same object, not burdening end users with having to think about
> exception safety.
>

And what if I don't agree that having some interfaces that throw and some
that crash constitutes a burden? It's easy to take the opposition viewpoint
and call it "anti-social". It's a lot harder to actually demonstrate that
it really is a problem in practice.

C++ is not a safe language, nor is it *going to be*.

I appreciate that all of these arguments make no sense to WG21 members. But
> you've got to remember you're all in the top 1% of C++ developers. You get
> this stuff. The average programmer does not, and curses all of you at WG21
> for not thinking of what it's like at the coal face.
>

So, you're effectively saying that if we don't agree with how you see
things, then we're just ivory tower intellectuals who don't care about how
the hoi-polloi suffer? That it is impossible for us to understand the needs
of "the average programmer" yet still disagree with you?

Has it occurred to you that we don't find your argument convincing
because... your argument is not convincing?

You then get significant C++ users banning all use of the STL in their
> major code bases precisely because of the anti-social-ness problem.
>

... they do? Whom?

As far as I am aware, most places that ban the standard library do so
because they're doing low-level stuff and can't afford to suffer the
performance irregularities of `vector`, `list`, and the like, or who have
very specific performance needs that these types cannot satisfy. It's not
that they don't want to use them; it's that they *can't*, because those
types don't do what they need.

Can you point to developers who have restricted themselves entirely from
using the standard library because of this supposed "anti-social-ness
problem"?

>
>>
>>>
>>> 2.2 What prevent implementation of expected to use a struct based when
>>> the types T, E are trivial. Could this be seen as a QoI?
>>>
>>
>> Discussed literally in the paper, with options discussed and a
>> recommendation made.
>>
>> Ok, so with the current wording an implementation could use a struct
>> based layout. But this is not enough to you. You want to force a specific
>> layout and not a QoI.
>> I'm not for adding this constraint to expected, other could agree with
>> you. The standard doesn't dictate a layout of the implementation data
>> members. It is only as if.
>> This could be a major reason to have a different class. The question1st
>> is if the committee wants this feature for expected.
>>
>
> I personally think WG21's historical attitude to good relations with other
> programming languages has been abysmal. No other programming language out
> there works well with C++, which is quite frankly shocking, and entirely
> the fault of WG21.
>

How exactly is not having a standard ABI WG21's fault? After all, it's not
like WG14 defined an ABI either. Stop castigating WG21 for things that
aren't actually their fault.

And moreover it's highly damaging to the long term sustainability of the
> C++ ecosystem. The most galling thing of all is that even little minor
> improvements in specification detail would deliver outsize improvements.
> There really ought to be a WG21 study group dedicated to deeply integrating
> C++ and Python together.
>

How do you write against something that isn't a standard? Python doesn't
have a standard, so how can you have a standard interface to it?

It would do wonders for our long term job prospects, and force the rest of
> WG21 to think about other people.
>

Yeah, everyone believes that if the committee solved *their* problems, then
everyone in the C++ world would be better off. What makes this such
declaration any different from anyone else's similar declarations?

Reply all
Reply to author
Forward
0 new messages