Subject: Re: [boost] [outcome] Possible extensions/changes to std::experimental::expected
From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2017-05-25 21:12:35
It looks like part of the discussion accidentally went into a private
conversation. So, here we are back.
2017-05-25 22:39 GMT+02:00 Vicente J. Botet Escriba <
> Le 25/05/2017 Ã 18:40, Andrzej Krzemienski a Ã©crit :
> 2017-05-25 17:32 GMT+02:00 Vicente J. Botet Escriba <
>> Le 25/05/2017 Ã 13:18, Andrzej Krzemienski via Boost a Ã©crit :
>>> 2017-05-25 9:44 GMT+02:00 Vicente J. Botet Escriba via Boost <
>>> We have now the possibility for uninitialized variables, but static
>>> analysis tools will help here.
>>> So, more specifically, I understand that you propose the following:
>>> - Default constructor works: no T or no E is construced (similar what
>>> outcome<> does)
>> I was not aware of this. Do you know that from this reference
>> constexpr outcome () noexcept(is_nothrow_default_constructible)
>> Default constructor.
> Well, I just assumed that since outcome<> has this empty state, it is
> exactly for the purpose of giving semantics to the default constructor. But
> now that you have asked, I looked at the docs. They say nothing about what
> happens in the default constructor. I tried to look in the code, but was
> confused with these policies. So, I just run a small test program, and yes:
> default constructor creates an empty state.
> Niall, please could you add an issue in order to document default
> constructors (if it doesn't already exists).
This is already logged in https://github.com/ned14/boost.outcome/issues/26
>> Sorrty, I couldn't interpret it as you.
>> But, if it is the case, yes, as outcome does.
>>> - You can assing to and and destroy such an objetc (similar what
>>> outcome<> does)
>> I don't catch what you mean here. Are you referring to the conversion
>> between expected with convertible value type and error types?
> No, I am saying that the following should work:
> outcome<T> o; // default-constructed
> o = some_outcome<T>(); // this should be safe to execute
> This works already with expected even if it doesn't defaults to empty.
Ok, and you expect it to continue to work.
>> - You will probably need to add an observer function that checks for
>>> this singular state, like `is_singular()`. If not for anything else
>>> would be used for assisting the static analysis tools. (again,
>>> similar what
>>> outcome<> does)
>> No. There will be no such observer. This is essential. There is no
>> visible empty state.
>> Or do you consider that chrono::duration should tell you if it was
>> initialized or not?
>> The user know if it is initialized or not, but there is no tool to check
>> This could be against safe programming, but we are here in C++ and we
>> should provide first the raw tools and then build on top of them when we
>> want more.
>>> - other observer functions (has_value(), value(), has_error(),
>>> cause UB when `is_singular() == true. (this is the only difference
>> Not the only one.
>> outcome fixes its error types. I'm proposing an extension to the current
>> expected so that it can take care of the Outcome use cases and needs.
>>> Did I understand your intentions correctly?
>> Not completly. I don't want an observer that tells me, attention you have
>> not initialized your variable, or you have moved from. This is essential.
> Very daring. It would be easier to accept if you could show a tool that is
> capable of statically analying this kind of "used unintialized" bug for
> Static analysis to check if uninitialized variables are used (read) works
> very well already . I don't remember if it si with clang-tidy that I have
> seen this kind of warnings.
Ok. Now I am thinking, another thing you can do, is to internally store
something like varient<T, Y, Empty> but do not expose this Empty in the
interface. Instead, rewrite observer functions like this:
bool has_value() const