Boost logo

Boost :

Subject: Re: [boost] [gsoc-2013] Boost.Expected
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2013-04-26 14:17:43


Le 26/04/13 14:22, Pierre T. a écrit :
> Hello,
>
> I wrote a proposal for the Boost.Expected project.
> You can find a pdf version here:
>
> http://hyc.io/boost/boost-expected-proposal.pdf
>
> It's about the Boost.Expected project, I'll add my own informations by
> the end of the week.
>
> Finally, I propose a single class design, and facilities for custom
> error code. It's based on the Alexendrescu idea upgraded by Vicente J.
> Botet Escriba and myself. I also took into account the Boost.Optional
> class. If needed for this proposal, I can add documentation per method
> (such as in official proposal), but I'm not sure it's useful without a
> frozen interface.
>
> Please do not hesitate to comment it and request further clarification,

Hi,

first of all, thanks for writing this proposal.

I have some concerns

* Single class:
I'm all for a single class; but having an ExceptionalType template
parameter which defaults to exception_ptr.

   template <typename ValueType, typename ExceptionalType=exception_ptr>
   class expected;

We could define the traits that make the difference between having an
exception_ptr and another error

     template <typename ExceptionalType>
     struct exceptional_traits {
       typedef ExceptionalType exceptional_type;
       template <class E>
       static exceptional_type make_exceptional(E const& except) {
         return exceptional_type(except)
       }
       static exceptional_type current_exceptional() {
         return exceptional_type()
       }
       static void rethrow(exceptional_type except) {
boost::throw_exception(bad_expected_access<exceptional_type>(except));
       }
     };
     template <>
     struct exceptional_traits<exception_ptr> {
       typedef ExceptionalType exceptional_type;

       template <class E>
       static exceptional_type make_exceptional(E const& except) {
         return boost::make_exception_ptr(except);
       }
       static exceptional_type current_exceptional() {
         return boost::current_exception()
       }
       static void rethrow(exceptional_type except); {
         boost::rethrow_exception(except);
       }
       template <class E>
       static bool has_exception(bool valid, exceptional_type except)
const BOOST_NOEXCEPT {
         try {
           if (!valid) rethrow(except);
         } catch (const E& ex) {
           return true;
         } catch (...) {
         }
         return false;
       }
     };
   }

With these traits we are able to define the functions that have a
specific behavior as e.g.

     typedef detail::exceptional_traits<ValueType, ExceptionalType> traits;

     expected() BOOST_NOEXCEPT
     : except_(traits::current_exceptional())
     , has_value_(false)
     {}
     const T& get() const
     {
       if (!valid()) traits::rethrow(except_);
       return value_;
     }
     template <class E>
     bool has_exception() const BOOST_NOEXCEPT
     {
       return traits::has_exception(except_);
     }

* Default Constructor or constructor from nullexpect
What is the advantage of having a expected instance that doesn't have
neither a value nor an exception?
How would the user manages with this possibility?
Are you looking to make expect movable?

* then/otherwise issues

Humm, I don't agree here with the proposed design (even if I made the
then suggestion). What returns the then function if the instance has a
value? I declared it as

     template <typename F>
     expected<typename boost::result_of<F(const expected&)>::type>
     then(F&& fuct)

Let me name
typedef typename boost::result_of<F(const expected&) RT;

so the result would return the expected<RT>(fuct(value_)). Chaining this
temporary with an otherwise call will work with the new temporary, and
not with the original expected.
I don't think this was what was expected ;-)

E.g.

   string f(int);
   int f(string);

   expected<int> e= 1;
   e.then(f).otherwise(g);

Here g will be called with expected<string>(fuct(value_)).except_. Hrrr

   expected<int> e= make_exceptional_expect(X);
   e.then(f).otherwise(g);

Here g will be called with the exception_ptr stored in e. Hrrr

That is g don't know if it is called with an exception stored on e or on
the temporary resulting for the call to f.

But the design error is not on the otherwise function but on the then
function.

Resuming, I'm not more for the 'then' function.

Using a visitor would as you proposed initially would be better.

     template <class V>
     void accept_visitor(V& visitor) const BOOST_NOEXCEPT
     {
       if (valid())
         visitor.visit(value_);
       else
         visitor.visit(expectional, except_);
     }

HTH,
Vicente


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk