1. Changes from r1
- 
     Add list of programming languages to proposed solution section 
- 
     Change map 
- 
     Update wording to use std :: monostate void 
2. Changes from r0
- 
     More notes on P0650 
- 
     Discussion about mapping of functions returning void 
3. Motivation
image get_cute_cat ( const image & img ) { return add_rainbow ( make_smaller ( make_eyes_sparkle ( add_bow_tie ( crop_to_cat ( img )))); } 
But there’s a problem. What if there’s not a cat in the picture? What if there’s no good place to add a bow tie? What if it has its back turned and we can’t make its eyes sparkle? Some of these operations could fail.
One option would be to throw exceptions on failure. However, there are many code bases which do not use exceptions for a variety of reasons. There’s also the possibility that we’re going to get lots of pictures without cats in them, in which case we’d be using exceptions for control flow. This is commonly seen as bad practice, and has an item warning against it in the C++ Core Guidelines.
Another option would be to make those operations which could fail return a 
std :: optional < image > get_cute_cat ( const image & img ) { auto cropped = crop_to_cat ( img ); if ( ! cropped ) { return std :: nullopt ; } auto with_tie = add_bow_tie ( * cropped ); if ( ! with_tie ) { return std :: nullopt ; } auto with_sparkles = make_eyes_sparkle ( * with_tie ); if ( ! with_sparkles ) { return std :: nullopt ; } return add_rainbow ( make_smaller ( * with_sparkles )); } 
Our code now has a lot of boilerplate to deal with the case where a
 step fails. Not only does this increase the noise and cognitive load of
 the function, but if we forget to put in a check, then suddenly we’re 
down the hole of undefined behaviour if we 
Another possibility would be to call 
std :: optional < image > get_cute_cat ( const image & img ) { try { auto cropped = crop_to_cat ( img ); auto with_tie = add_bow_tie ( cropped . value ()); auto with_sparkles = make_eyes_sparkle ( with_tie . value ()); return add_rainbow ( make_smaller ( with_sparkles . value ())); catch ( std :: bad_optional_access & e ) { return std :: nullopt ; } } 
Again, this is using exceptions for control flow. There must be a better way.
4. Proposed solution
This paper proposes adding additional member functions to 
std :: optional < image > get_cute_cat ( const image & img ) { return crop_to_cat ( img ) . and_then ( add_bow_tie ) . and_then ( make_eyes_sparkle ) . map ( make_smaller ) . map ( add_rainbow ); } 
We’ve successfully got rid of all the manual checking. We’ve even improved on the clarity of the non-optional example, which needed to either be read inside-out or split into multiple declarations.
This is common in other programming languages. Here is a list of programming languages which have a 
- 
     Java: Optional 
- 
     Swift: Optional 
- 
     Haskell: Maybe 
- 
     Rust: Option 
- 
     OCaml: option 
- 
     Scala: Option 
- 
     Agda: Maybe 
- 
     Idris: Maybe 
- 
     Kotlin: T ? 
- 
     StandardML: option 
- 
     C#: Nullable 
Here is a list of programming languages which have a 
- 
     C++ 
- 
     I couldn’t find any others 
All that we need now is an understanding of what 
4.1. map 
   
For example, if you have a 
auto  s  =  opt_string . map ([]( auto &&  s )  {  return  s . size ();  }); which is somewhat equivalent to:
if ( opt_string ) { std :: size_t s = opt_string -> size (); } 
template < class T > class optional { template < class Return > std :: optional < Return > map ( function < Return ( T ) > func ); }; 
It takes any callable object (like a function). If the 
If you come from a functional programming or category theory background, you may recognise this as a functor map.
4.2. and_then 
   
For example, say you have 
std :: optional < int >  i  =  opt_string . and_then ( stoi ); Which is roughly equivalent to:
if ( opt_string ) { std :: optional < int > i = stoi ( * opt_string ); } 
template < class T > class optional { template < class Return > std :: optional < Return > and_then ( function < std :: optional < Return > ( T ) > func ); }; 
It takes any callable object which returns a 
Again, those from an FP background will recognise this as a monadic bind.
4.3. or_else 
   
get_opt (). or_else ([]{ std :: cout << "get_opt failed" ;}); get_opt (). or_else ([]{ throw std :: runtime_error ( "get_opt_failed" )}); 
Users can easily abstract these patterns if they are common:
void opt_log ( std :: string_view msg ) { return [ = ] { std :: cout << msg ; }; } void opt_throw ( std :: string_view msg ) { return [ = ] { throw std :: runtime_error ( msg ); }; } get_opt (). or_else ( opt_log ( "get_opt failed" )); get_opt (). or_else ( opt_throw ( "get_opt failed" )); 
It has one overload (expositional):
template < class T > class optional { template < class Return > std :: optional < T > or_else ( function < Return () > func ); }; 
4.4. Chaining
With these two functions, doing a lot of chaining of functions which could fail becomes very clean:
std :: optional < int > foo () { return a (). and_then ( b ) . and_then ( c ) . and_then ( d ) . and_then ( e ); } 
Taking the example of 
std :: optional < int > i = opt_string . and_then ( stoi ) . map ([]( auto i ) { return i * 2 ; }); 
We can also intersperse our chain with error checking code:
std :: optional < int > i = opt_string . and_then ( stoi ) . or_else ( opt_throw ( "stoi failed" )) . map ([]( auto i ) { return i * 2 ; }); 
5. How other languages handle this
Rust has an 
6. Considerations
6.1. Mapping functions returning void 
   There are three main options for handling 
get_optional () // returns std::optional<T> . map ( print_value ) // returns std::optional<std::monostate> . map ( notify_success ); // Is only called when get_optional returned a value 
6.2. More functions
Rust’s Option class provides a lot more than 
6.3. map 
   It would be possible to merge all of these into a single function which handles all use cases. However, I think this would make the function more difficult to teach and understand.
6.4. Operator overloading
We could provide operator overloads with the same semantics as the functions. For example, 
// original crop_to_cat ( img ) . and_then ( add_bow_tie ) . and_then ( make_eyes_sparkle ) . map ( make_smaller ) . map ( add_rainbow ); // rewritten crop_to_cat ( img ) >= add_bow_tie >= make_eyes_sparkle | make_smaller | add_rainbow ; 
Another option would be 
6.5. Applicative Functors
template < class Return > std :: optional < Return > map ( std :: optional < function < Return ( T ) >> func ); 
This would give functional programmers the set of operations which they may expect from a monadic-style interface. However, I couldn’t think of many use-cases of this in C++. If some are found then we could add the extra overload.
6.6. Alternative names
Alternative names for 
6.7. Overloaded and_then 
   Instead of an additional 
o . and_then ( a ,  []{ throw  std :: runtime_error ( "oh no" );}); The above will throw if 
7. Pitfalls
Users may want to write code like this:
std :: optional < int > foo ( int i ) { return a (). and_then ( b ) . and_then ( get_func ( i )); } 
The problem with this is 
One possible solution to this would be to add an additional function, 
std :: optional < int > foo ( int i ) { return a (). and_then ( b ) . bind_with ([ i ](){ return get_func ( i )}); } 
7.1. Other solutions
There is a proposal for adding a general monadic interface
 to C++. Unfortunately doing the kind of composition described above 
would be very verbose with the current proposal without some kind of 
Haskell-style 
std :: optional < int > get_cute_cat ( const image & img ) { return functor :: map ( functor :: map ( monad :: bind ( monad :: bind ( crop_to_cat ( img ), add_bow_tie ), make_eyes_sparkle ), make_smaller ), add_rainbow ); } 
My proposal is not necessarily an alternative to this proposal; compatibility between the two could be ensured and the generic proposal could use my proposal as part of its implementation. This would allow users to use both the generic syntax for flexibility and extensibility, and the member-function syntax for brevity and clarity.
If 
Another option would be to use a ranges-style interface for the general monadic interface:
std :: optional < int > get_cute_cat ( const image & img ) { return crop_to_cat ( img ) | monad :: bind ( add_bow_tie ) | monad :: bind ( make_eyes_sparkle ) | functor :: map ( make_smaller ) | functor :: map ( add_rainbow ); } 
7.2. Interaction with other proposals
There is a proposal for std::expected
 which would benefit from many of these same ideas. If the idea to add 
monadic interfaces to standard library classes on a case-by-case basis 
is chosen rather than a unified non-member function interface, then 
compatibility between this proposal and the 
Mapping functions which return 
Any proposals which make lambdas or overload sets easier to write and pass around will greatly improve this proposal. In particular, proposals for lift operators and abbreviated lambdas would ensure that the clean style is preserved in the face of many anonymous functions and overloads.
If an operator overloading approach is taken and the workflow operator (
8. Implementation experience
This proposal has been implemented here.
9. Proposed Wording
9.1. New synopsis entry: [ optional . monadic ] 
template < class F > constexpr * see below * and_then ( F && f ) & ; template < class F > constexpr * see below * and_then ( F && f ) && ; template < class F > constexpr * see below * and_then ( F && f ) const & ; template < class F > constexpr * see below * and_then ( F && f ) const && ; template < class F > constexpr * see below * map ( F && f ) & ; template < class F > constexpr * see below * map ( F && f ) && ; template < class F > constexpr * see below * map ( F && f ) const & ; template < class F > constexpr * see below * map ( F && f ) const && ; template < class F > constexpr optional < T > or_else ( F && f ) & ; template < class F > constexpr optional < T > or_else ( F && f ) && ; template < class F > constexpr optional < T > or_else ( F && f ) const & ; template < class F > constexpr optional < T > or_else ( F && f ) const && ; 
9.2. New section: Monadic operations [ optional . monadic 
template < class F > constexpr * see below * and_then ( F && f ) & ; template < class F > constexpr * see below * and_then ( F && f ) const & ; 
Requires: 
Returns: Let 
template < class F > constexpr * see below * and_then ( F && f ) && ; template < class F > constexpr * see below * and_then ( F && f ) const && ; 
Requires: 
Returns: Let 
template < class F > constexpr * see below * map ( F && f ) & ; template < class F > constexpr * see below * map ( F && f ) const & ; 
Returns: Let 
- 
     If U void std :: optional < std :: monostate > * this f std :: invoke ( std :: forward < F > ( f ), value ()) optional std :: monostate optional 
- 
     If U void std :: optional < U > * this optional < U > std :: invoke ( std :: forward < F > ( f ), value ()) optional 
template < class F > constexpr * see below * map ( F && f ) && ; template < class F > constexpr * see below * map ( F && f ) const && ; 
Returns: Let 
- 
     If U void std :: optional < std :: monostate > * this f std :: invoke ( std :: forward < F > ( f ), std :: move ( value ())) optional std :: monostate optional 
- 
     If U void std :: optional < U > * this optional < U > std :: invoke ( std :: forward < F > ( f ), std :: move ( value ()) optional 
template < class F > constexpr optional < T > or_else ( F && f ) & ; template < class F > constexpr optional < T > or_else ( F && f ) const & ; 
Requires: 
Effects: If 
template < class F > constexpr optional < T > or_else ( F && f ) && ; template < class F > constexpr optional < T > or_else ( F && f ) const && ; 
Requires: 
Effects: If 
9.3. Acknowledgements
Thank you to Michael Wong for representing this paper to the committee. Thanks to Kenneth Benzie, Vittorio Romeo, Jonathan Müller, Adi Shavit, Nicol Bolas, Vicente Escribá and Barry Revzin for review and suggestions.