[boost.cobalt] A precondition or an error condition?

From the perspective of the library author, you can now, for the event of
Hi Everyone,
I would like to discuss one correctness aspect of Boost.COBALT. We have
this list and the Slack channel, so I am not sure which place is better.
Let me do it here.
In Boost.Cobalt (formerly Boost.Async) we have function cobalt::race
(formerly select()) that takes a range of awaitables `p` and returns an
awaitable capable on awaiting on one of the elements of `p`:
https://www.boost.org/doc/libs/develop/libs/cobalt/doc/html/index.html#race-...
Example:
```
promise<string> talk_to_server_1();
promise<string> talk_to_server_2();
promise<string> timeout_with_default();
vector

On Thu, Nov 9, 2023 at 9:41 PM Andrzej Krzemienski via Boost
I don't see why this is a correctness issue and not a design choice. When is it correct to use an exception?
This example doesn't help, because this should obviously use the
variadic version.
The reason to use the ranged one is for when you have another
component dictating what elements to listen to.
try
{
vector

czw., 9 lis 2023 o 15:09 Klemens Morgenstern < klemensdavidmorgenstern@gmail.com> napisał(a):
Thanks Klemens. This is very useful information (when to use which overload), and I recommend that it should be put in the documentation. Stil, I do not feel convinced. Your example illustrates, I think, the situation where an untrusted external input is passed unvalidated to the guts of the program. I would never like to encourage or support this way of writing servers. Of course, people will still do it, and it is prudent of you to be prepared for it, but I would still strongly insist that your library calls this usage a bug: that is something that the programmer should fix as soon as they can. It doesn't prevent you from throwing exceptions, but you have an opportunity to additionally discourage the use like this (via warnings, crashes in debug mode, additional control flows in debugger).
To some extent, this is your choice as a library author. But I am trying to set up a guideline or a policy applicable to a range of libraries. The uncontroversial circumstance that warrants a throw, is when a function cannot deliver its promise, but the caller couldn't have known about it when calling a function: ``` File f ("C:/folder/filename.cfg"); ``` Here I checked that the file existed one millisecond ago. I requested for it to be open, but the OS determined that the file is no longer there. There was nothing I can do to guarantee that the file would be openable. The case with `race` is different. There is a very simple way of checking the empty-range, and it never can produce a meaningful result. Regards, &rzej;

Le 2023-11-09 14:41, Andrzej Krzemienski via Boost a écrit :
I agree with you. However, there are pros and cons of both approaches (UB for contract violation, or broader contract and defined behaviour with exception thrown). In all cases, "throw an exception" is not a sufficient specification. The contract must clearly state which exception is thrown. This is like the good old vector/array operator[] vs at(). There are use cases for both.
I think that as much as possible should be done using the type system
and the compiler, because this is what is checked at compile time. In
that particular case, i think that:
template

Le 2023-11-09 16:21, Klemens Morgenstern via Boost a écrit :
On Thu, Nov 9, 2023 at 11:00 PM Julien Blanc via Boost
wrote:
range<awaitable> is already pseudo-code, so i'm not sure why you ask. But you're right, i've been mislead by the current doc. I was going to reply that it could at the very least be defined as: template<typename T> concept non_empty_range = std::ranges::range<T>; // self-documenting alias. Gives opportunity for future improvements However, this is not what we want here. What we want here is a non_empty range of<awaitable>. So i believe the correct documentation should be non_empty_range_of<awaitable>. Of course, it's still pseudo-code. This makes me rises the concern about using pseudo-code in the documentation, without telling so. Especially with features the reader might not be familiar with, such as concepts and coroutines, which . Maybe there should be a convention across the documentation to differentiate between valid c++ code and pseudo-code (pseudo-code is useful for clarity in certain situations). In all cases, i think that a misleading pseudo-code is a documentation bug that should be fixed. A library targetting c++20 should not misuse the "range" name. Best regards, Julien
participants (3)
-
Andrzej Krzemienski
-
Julien Blanc
-
Klemens Morgenstern