Date: Sun, 11 Oct 2020 15:24:09 -0300
Thanks. Dmitry. I've already made a working std::expected implementation
that has an expected<void, E> specialization. The void specialization
wasn't as difficult as I had feared, but there is a fair amount of code
duplication. In the absence of constexpr if (I'm constrained to C++11), I
could try to find other metaprogramming ways of avoiding the duplication,
but I fear it would just obfuscate the code.
If I need further advice on implementation details, I'll ask on another
more appropriate forum.
On Sun, Oct 11, 2020 at 3:10 PM Dmitry Dmitry <dimanne_at_[hidden]> wrote:
> As I understand it, expected is supposed to be a "vocabulary type" similar
>> to std::optional, or std::variant, yet the latter two don't permit void as
>> one of their contained types (as far as I know).
>
>
> If this is the main problem, then partial specialisation of your
> expected<> for void can solve the issue. You can have a look at what I mean
> in my implementation of Result<Ok, Err> here
> <https://github.com/DimanNe/result/blob/master/src/result.h>.
>
> On Sun, Oct 4, 2020 at 10:21 PM Emile Cormier via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Hi Everyone. This is my first time posting to this group, so please be
>> gentle. :-)
>>
>> I'm in need of a value-or-error mechanism for a C++11 library I'm working
>> on, where I don't want to impose exceptions to the client. Having completed
>> a toy "result<T, E>" implementation inspired by std::expected, I decided to
>> implement a complete C++11-ized version of the P0323R9 proposal.
>>
>> I am questioning the rationale of allowing void as a value type for
>> std::expected. As I understand it, expected is supposed to be a "vocabulary
>> type" similar to std::optional, or std::variant, yet the latter two don't
>> permit void as one of their contained types (as far as I know).
>>
>> The spec for std::expected is currently very complex with constraints on
>> overloads. expected(const expected<U, G>& rhs) in particular is quite scary
>> and makes me wonder if it can slow down compilations times. Not having to
>> worry about the T=void case would simplify things.
>>
>> If a user wants to use std::expected to indicate a success-or-failure
>> result (with no value), they could simply use something like std::monostate
>> as the value type. What I did in my toy result<T,E> implementation is
>> provide an empty success_t tag type that can be used when there is no
>> meaningful value to return. For example:
>>
>> struct success_t
>> {
>> constexpr success_t() = default;
>> constexpr bool operator==(success_t) const {return true;}
>> constexpr bool operator!=(success_t) const {return false;}
>> };
>> inline constexpr success_t successful;
>>
>> result<success_t, std::error_code> write(const std::string& str)
>> {
>> if (writeToDeviceWorks(str))
>> return successful;
>> else
>> return
>> with_failure(make_error_code(std::errc::device_or_resource_busy));
>> // with_failure is my equivalent of unexpected(), where I don't
>> have the
>> // luxury of CTAD in C++11.
>> }
>>
>> int main()
>> {
>> auto res = write("foo");
>> if (res == successful)
>> std::cout << "Yay!\n";
>> else
>> std::cerr << "Oh no: " << res.error() << "\n";
>> }
>>
>> The "successful" object has the benefit that it's quite readable when
>> used on the RHS of operator==, as shown above.
>>
>> The one benefit of allowing T=void I can see is that a
>> std::expected<void, E> specialization can get rid of its union storage and
>> directly store error_type. Is this the rationale for allowing
>> std::expected<void, E>?
>>
>> Cheers,
>> Emile Cormier
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>
>
> --
> Dmitry
> *Sent from gmail*
>
that has an expected<void, E> specialization. The void specialization
wasn't as difficult as I had feared, but there is a fair amount of code
duplication. In the absence of constexpr if (I'm constrained to C++11), I
could try to find other metaprogramming ways of avoiding the duplication,
but I fear it would just obfuscate the code.
If I need further advice on implementation details, I'll ask on another
more appropriate forum.
On Sun, Oct 11, 2020 at 3:10 PM Dmitry Dmitry <dimanne_at_[hidden]> wrote:
> As I understand it, expected is supposed to be a "vocabulary type" similar
>> to std::optional, or std::variant, yet the latter two don't permit void as
>> one of their contained types (as far as I know).
>
>
> If this is the main problem, then partial specialisation of your
> expected<> for void can solve the issue. You can have a look at what I mean
> in my implementation of Result<Ok, Err> here
> <https://github.com/DimanNe/result/blob/master/src/result.h>.
>
> On Sun, Oct 4, 2020 at 10:21 PM Emile Cormier via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Hi Everyone. This is my first time posting to this group, so please be
>> gentle. :-)
>>
>> I'm in need of a value-or-error mechanism for a C++11 library I'm working
>> on, where I don't want to impose exceptions to the client. Having completed
>> a toy "result<T, E>" implementation inspired by std::expected, I decided to
>> implement a complete C++11-ized version of the P0323R9 proposal.
>>
>> I am questioning the rationale of allowing void as a value type for
>> std::expected. As I understand it, expected is supposed to be a "vocabulary
>> type" similar to std::optional, or std::variant, yet the latter two don't
>> permit void as one of their contained types (as far as I know).
>>
>> The spec for std::expected is currently very complex with constraints on
>> overloads. expected(const expected<U, G>& rhs) in particular is quite scary
>> and makes me wonder if it can slow down compilations times. Not having to
>> worry about the T=void case would simplify things.
>>
>> If a user wants to use std::expected to indicate a success-or-failure
>> result (with no value), they could simply use something like std::monostate
>> as the value type. What I did in my toy result<T,E> implementation is
>> provide an empty success_t tag type that can be used when there is no
>> meaningful value to return. For example:
>>
>> struct success_t
>> {
>> constexpr success_t() = default;
>> constexpr bool operator==(success_t) const {return true;}
>> constexpr bool operator!=(success_t) const {return false;}
>> };
>> inline constexpr success_t successful;
>>
>> result<success_t, std::error_code> write(const std::string& str)
>> {
>> if (writeToDeviceWorks(str))
>> return successful;
>> else
>> return
>> with_failure(make_error_code(std::errc::device_or_resource_busy));
>> // with_failure is my equivalent of unexpected(), where I don't
>> have the
>> // luxury of CTAD in C++11.
>> }
>>
>> int main()
>> {
>> auto res = write("foo");
>> if (res == successful)
>> std::cout << "Yay!\n";
>> else
>> std::cerr << "Oh no: " << res.error() << "\n";
>> }
>>
>> The "successful" object has the benefit that it's quite readable when
>> used on the RHS of operator==, as shown above.
>>
>> The one benefit of allowing T=void I can see is that a
>> std::expected<void, E> specialization can get rid of its union storage and
>> directly store error_type. Is this the rationale for allowing
>> std::expected<void, E>?
>>
>> Cheers,
>> Emile Cormier
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>
>
> --
> Dmitry
> *Sent from gmail*
>
Received on 2020-10-11 13:24:22