martinmoene / expected-dark

Expected objects for C++11 and later (and later perhaps C++98 )
MIT License
52 stars 4 forks source link

value method is broken for non std::exception_ptr specializations #15

Closed rnburn closed 6 years ago

rnburn commented 6 years ago

This code should work

#include "expected.hpp"
#include <system_error>

int main() {
  nonstd::expected<int, std::error_code> e = 12;
  (void)e.value();
  return 0;
}

But it gives this compilation error:

Ryans-MacBook-Pro:expected-lite ryanburn$ clang++ -std=c++11 main.cpp
In file included from main.cpp:1:
./expected.hpp:113:29: warning: 'constexpr' non-static member function will not be implicitly 'const' in
      C++14; add 'const' to avoid a change in behavior [-Wconstexpr-not-const]
    constexpr value_type && value() &&
                            ^
                                    const
./expected.hpp:637:29: warning: 'constexpr' non-static member function will not be implicitly 'const' in
      C++14; add 'const' to avoid a change in behavior [-Wconstexpr-not-const]
    constexpr value_type && operator *() &&
                            ^
                                         const
./expected.hpp:670:29: warning: 'constexpr' non-static member function will not be implicitly 'const' in
      C++14; add 'const' to avoid a change in behavior [-Wconstexpr-not-const]
    constexpr value_type && value() &&
                            ^
                                    const
./expected.hpp:689:29: warning: 'constexpr' non-static member function will not be implicitly 'const' in
      C++14; add 'const' to avoid a change in behavior [-Wconstexpr-not-const]
    constexpr error_type && error() &&
                            ^
                                    const
./expected.hpp:911:29: warning: 'constexpr' non-static member function will not be implicitly 'const' in
      C++14; add 'const' to avoid a change in behavior [-Wconstexpr-not-const]
    constexpr error_type && error() &&
                            ^
                                    const
./expected.hpp:666:41: error: no viable conversion from 'error_type' (aka 'std::__1::error_code') to
      'std::exception_ptr'
            ? ( std::rethrow_exception( contained.error() ), contained.value() )
                                        ^~~~~~~~~~~~~~~~~
main.cpp:6:11: note: in instantiation of member function 'nonstd::expected<int, std::__1::error_code>::value'
      requested here
  (void)e.value();
          ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/exception:131:31: note:
      candidate constructor not viable: no known conversion from 'error_type' (aka 'std::__1::error_code') to
      'nullptr_t' for 1st argument
    _LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}
                              ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/exception:132:5: note:
      candidate constructor not viable: no known conversion from 'error_type' (aka 'std::__1::error_code') to
      'const std::exception_ptr &' for 1st argument
    exception_ptr(const exception_ptr&) _NOEXCEPT;
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/exception:148:65: note:
      passing argument to parameter here
    friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);
                                                                ^
5 warnings and 1 error generated.

The believe the specializations for std::exception_ptr should be using std::enable_if instead of regular conditionals.

martinmoene commented 6 years ago

Thanks!

viboes commented 6 years ago

I guess you know that the error_traits is not part of the current proposal.

The proposal has nothing special for exception_ptr or error_code.

I believe that we can define a non-member non-friend function that could do what we want on top of the proposal.

E.g. we can have value_or_rethrow that could make use or error_traits.

In [P0786] I propose a resolve function that could take a function that rethrows as well.

using namespace value_or_error;
auto v = resolve(e, rethrow);

where retrow would be a polymorphic function that rethrows using the error_traits.

So value_or_rethrow(e) coudl be the equivalent to resolve(e, rethrow)

I recognize the syntax of the non-member functions is less friendly for a lot of us, but I believe that we should define the minimal interface in expected. At the end, expected::value and expected::value_or shouldn't be member functions, as we can define them as non-members.

BTW, I'm working with JF Bastien on the wording for the LWG. See https://github.com/jfbastien/papers/blob/master/source/D0323r4.bs

Any contribution is more than welcome.

[d0786r1] https://github.com/viboes/std-make/blob/master/doc/proposal/value_or_error/d0786r1.md