Awesome Open Source
Awesome Open Source

expected lite - expected objects for C++11 and later

Language Standard License Build Status Build status Version download Try it online

expected lite is a single-file header-only library for objects that either represent a valid value or an error that you can pass by value. It is intended for use with C++11 and later. The library is based on the std::expected proposal [1] .

Contents

Example usage

#include "expected.hpp"

#include <cstdlib>
#include <iostream>
#include <string>

using namespace nonstd;
using namespace std::literals;

auto to_int( char const * const text ) -> expected<int, std::string> 
{
    char * pos = nullptr;
    auto value = strtol( text, &pos, 0 );

    if ( pos != text ) return value;
    else               return make_unexpected( "'"s + text + "' isn't a number" );
}

int main( int argc, char * argv[] )
{
    auto text = argc > 1 ? argv[1] : "42";

    auto ei = to_int( text );

    if ( ei ) std::cout << "'" << text << "' is " << *ei << ", ";
    else      std::cout << "Error: " << ei.error();
}

Compile and run

prompt> g++ -std=c++14 -Wall -I../include/nonstd -o 01-basic.exe 01-basic.cpp && 01-basic.exe 123 && 01-basic.exe abc
'123' is 123, Error: 'abc' isn't a number

In a nutshell

expected lite is a single-file header-only library to represent value objects that either contain a valid value or an error. The library is a partly implementation of the proposal for std::expected [1,2,3] for use with C++11 and later.

Some Features and properties of expected lite are ease of installation (single header), default and explicit construction of an expected, construction and assignment from a value that is convertible to the underlying type, copy- and move-construction and copy- and move-assignment from another expected of the same type, testing for the presence of a value, operators for unchecked access to the value or the error (pointer or reference), value() and value_or() for checked access to the value, relational operators, swap() and various factory functions.

Not provided are reference-type expecteds. expected lite doesn't handle overloaded address of operators.

For more examples, see [1].

License

expected lite uses the MIT license.

Dependencies

expected lite has no other dependencies than the C++ standard library.

Installation

expected lite is a single-file header-only library. Put expected.hpp directly into the project source tree or somewhere reachable from your project.

Synopsis

Contents

Configuration macros

-Dnsel_CONFIG_CONFIRMS_COMPILATION_ERRORS=0
Define this macro to 1 to experience the by-design compile-time errors of the library in the test suite. Default is 0.

Types in namespace nonstd

Purpose Type Object
To be, or not template< typename T, typename E = std::exception_ptr >
class expected;
 
Error type template< typename E >
class unexpected_type;
 
Traits template< typename E >
struct is_unexpected;
 
In-place value construction struct in_place_t; in_place_t in_place{};
In-place error construction struct in_place_unexpected_t; in_place_unexpected_t
unexpect{};
In-place error construction struct in_place_unexpected_t; in_place_unexpected_t
in_place_unexpected{};
Error reporting class bad_expected_access;  

Interface of expected

Kind Method Result
Construction [constexpr] expected() noexcept(...) an object with default value
  [constexpr] expected( expected const & other ) initialize to contents of other
  [constexpr] expected( expected && other ) move contents from other
  [constexpr] expected( value_type const & value ) initialize to value
  [constexpr] expected( value_type && value ) noexcept(...) move from value
  [constexpr] explicit expected( in_place_t, Args&&... args ) construct value in-place from args
  [constexpr] explicit expected( in_place_t,
 std::initializer_list<U> il, Args&&... args )
construct value in-place from args
  [constexpr] expected( unexpected_type const & error ) initialize to error
  [constexpr] expected( unexpected_type && error ) move from error
  [constexpr] explicit expected( in_place_unexpected_t,
 Args&&... args )
construct error in-place from args
  [constexpr] explicit expected( in_place_unexpected_t,
 std::initializer_list<U> il, Args&&... args )
construct error in-place from args
Destruction ~expected() destruct current content
Assignment expected operator=( expected const & other ) assign contents of other;
destruct current content, if any
  expected & operator=( expected && other ) noexcept(...) move contents of other
  expected & operator=( U && v ) move value from v
  expected & operator=( unexpected_type const & u ) initialize to unexpected
  expected & operator=( unexpected_type && u ) move from unexpected
  template< typename... Args >
void emplace( Args &&... args )
emplace from args
  template< typename U, typename... Args >
void emplace( std::initializer_list<U> il, Args &&... args )
emplace from args
Swap void swap( expected & other ) noexcept swap with other
Observers constexpr value_type const * operator->() const pointer to current content (const);
must contain value
  value_type * operator->() pointer to current content (non-const);
must contain value
  constexpr value_type const & operator *() const & the current content (const ref);
must contain value
  constexpr value_type && operator *() && the current content (non-const ref);
must contain value
  constexpr explicit operator bool() const noexcept true if contains value
  constexpr has_value() const noexcept true if contains value
  constexpr value_type const & value() const & current content (const ref);
see note 1
  value_type & value() & current content (non-const ref);
see note 1
  constexpr value_type && value() && move from current content;
see note 1
  constexpr error_type const & error() const & current error (const ref);
must contain error
  error_type & error() & current error (non-const ref);
must contain error
  constexpr error_type && error() && move from current error;
must contain error
  constexpr unexpected_type get_unexpected() const the error as unexpected<>;
must contain error
  template< typename Ex >
bool has_exception() const
true of contains exception (as base)
  value_type value_or( U && v ) const & value or move from v
  value_type value_or( U && v ) && move from value or move from v
  ...  

Note 1: checked access: if no content, for std::exception_ptr rethrows error(), otherwise throws bad_expected_access(error()).

Algorithms for expected

Kind Function
Relational operators  
== != < > <= >= template< typename T, typename E >
constexpr bool operator op(
 expected<T,E> const & x,
 expected<T,E> const & y )
Comparison with unexpected_type  
== != < > <= >= template< typename T, typename E >
constexpr bool operator op(
 expected<T,E> const & x,
 unexpected_type<E> const & u )
  template< typename T, typename E >
constexpr bool operator op(
 unexpected_type<E> const & u,
 expected<T,E> const & x )
Comparison with T  
== != < > <= >= template< typename T, typename E >
constexpr bool operator op(
 expected<T,E> const & x,
 T const & v )
  template< typename T, typename E >
constexpr bool operator op(
 T const & v,
 expected<T,E> const & x )
Specialized algorithms  
Swap template< typename T, typename E >
void swap(
 expected<T,E> & x,
 expected<T,E> & y ) noexcept( noexcept( x.swap(y) ) )
Make expected from  
 Value template< typename T>
constexpr auto make_expected( T && v ) ->
 expected< typename std::decay<T>::type >
 Nothing auto make_expected() -> expected<void>
 Current exception template< typename T>
constexpr auto make_expected_from_current_exception() -> expected<T>
 Exception template< typename T>
auto make_expected_from_exception( std::exception_ptr v ) -> expected<T>
 Error template< typename T, typename E >
constexpr auto make_expected_from_error( E e ) ->
 expected<T, typename std::decay<E>::type>
 Call template< typename F >
auto make_expected_from_call( F f ) ->
 expected< typename std::result_of<F()>::type >
 Call, void specialization template< typename F >
auto make_expected_from_call( F f ) -> expected<void>

Interface of unexpected_type

Kind Method Result
Construction unexpected_type() = delete; no default construction
  constexpr explicit unexpected_type( E const & error ) copy-constructed from an E
  constexpr explicit unexpected_type( E && error ) move-constructed from an E
Observers constexpr error_type const & value() const can observe contained error
  error_type & value() can modify contained error

Algorithms for unexpected_type

Kind Function
Relational operators  
== != < > <= >= template< typename E >
constexpr bool operator op(
 unexpected_type<E> const & x,
 unexpected_type<E> const & y )
== != < > <= >= constexpr bool operator op(
 unexpected_type<std::exception_ptr> const & x,
 unexpected_type<std::exception_ptr> const & y )
Specialized algorithms  
Make unexpected from  
 Current exception [constexpr] auto make_unexpected_from_current_exception() ->
 unexpected_type< std::exception_ptr >
 Error template< typename E>
[constexpr] auto make_unexpected( E && v) ->
 unexpected_type< typename std::decay<E>::type >

Comparison with like types

Feature
std::pair
std:: optional std:: expected nonstd:: expected Boost. Expected Nonco expected Andrei Expected Hagan required
More information see [14] see [5] see [1] this work see [4] see [7] see [8] see [13]
C++03 yes no no no/not yet no (union) no no yes
C++11 yes no no yes yes yes yes yes
C++14 yes no no yes yes yes yes yes
C++17 yes yes no yes yes yes yes yes
DefaultConstructible T param yes yes yes yes no no no
In-place construction no yes yes yes yes yes no no
Literal type yes yes yes yes yes no no no
Disengaged information possible no yes yes yes yes yes no
Vary disengaged type yes no yes yes yes no no no
Engaged nonuse throws no no no no error_traits no no yes
Disengaged use throws no yes, value() yes, value() yes, value() yes,
value()
yes,
get()
yes,
get()
n/a
Proxy (rel.ops) no yes yes yes yes no no no
References no yes no/not yet no/not yet no/not yet yes no no
Chained visitor(s) no no yes maybe yes no no no

Note 1: std::experimental::expected

Note 2: sources for Nonco expected, Andrei Expected and Hagan required can befound in the spike-expected repository.

Reported to work with

Implementation notes

Other implementations of expected

Notes and references

[1] Vicente J. Botet Escriba. p0323 - A proposal to add a utility class to represent expected object (latest) (PDF). (r6, r5, r4, r3, r2, r1, r0, draft).

[2] Vicente J. Botet Escriba. JASEL: Just a simple experimental library for C++. Reference implementation of expected.

[3] Vicente J. Botet Escriba. Expected - An exception-friendly Error Monad. C++Now 2014. 24 September 2014.

[4] Pierre Talbot. Boost.Expected. Unofficial Boost candidate. 5 May 2013. GitHub, GSoC 2013 Proposal, [email protected].

[5] Fernando Cacciola and Andrzej Krzemieński. A proposal to add a utility class to represent optional objects (Revision 4). ISO/IEC JTC1 SC22 WG21 N3672 2013-04-19.

[6] Andrzej Krzemieński, Optional library implementation in C++11.

[7] Anto Nonco. Extending expected to deal with references. 27 May 2013.

[8] Andrei Alexandrescu. Systematic Error Handling in C++. Prepared for The C++and Beyond Seminar 2012. Video. Slides.

[9] Andrei Alexandrescu. Choose your Poison: Exceptions or Error Codes? (PDF). ACCU Conference 2007.

[10] Andrei Alexandrescu. The Power of None (PPT). Northwest C++ Users' Group. May 17th, 2006.

[11] Jon Jagger. A Return Type That Doesn't Like Being Ignored. Overload issue 53, February 2003.

[12] Andrei Alexandrescu. Error Handling in C++: Are we inching towards a total solution?. ACCU Conference 2002.

[13] Ken Hagan et al. Exploding return codes. comp.lang.c++.moderated. 11 February 2000.

[14] std::pair. cppreference.com

[15] Niall Douglas. Outcome. Very lightweight outcome<T> and result<T> (non-Boost edition).

Appendix

A.1 expected lite test specification

unexpected_type<>: Disallows default construction
unexpected_type<>: Disallows default construction, std::exception_ptr specialization
unexpected_type<>: Allows to copy-construct from error_type
unexpected_type<>: Allows to copy-construct from error_type, std::exception_ptr specialization
unexpected_type<>: Allows to move-construct from error_type
unexpected_type<>: Allows to move-construct from error_type, std::exception_ptr specialization
unexpected_type<>: Allows to copy-construct from an exception, std::exception_ptr specialization
unexpected_type<>: Allows to observe its value
unexpected_type<>: Allows to observe its value, std::exception_ptr specialization
unexpected_type<>: Allows to modify its value
unexpected_type<>: Allows to modify its value, std::exception_ptr specialization
unexpected_type<>: Provides relational operators
unexpected_type<>: Provides relational operators, std::exception_ptr specialization
is_unexpected<X>: Is true for unexpected_type
is_unexpected<X>: Is false for non-unexpected_type (int)
make_unexpected(): Allows to create an unexpected_type<E> from an E
make_unexpected_from_current_exception(): Allows to create an unexpected_type<std::exception_ptr> from the current exception
bad_expected_access<>: Disallows default construction
bad_expected_access<>: Allows construction from error_type
bad_expected_access<>: Allows to observe its error
bad_expected_access<>: Allows to change its error
expected<>: Allows default construction
expected<>: Allows to copy-construct from value_type
expected<>: Allows to move-construct from value_type
expected<>: Allows to copy-construct from expected<>
expected<>: Allows to move-construct from expected<>
expected<>: Allows to in-place-construct value_type
expected<>: Allows to copy-construct from unexpected_type<>
expected<>: Allows to move-construct from unexpected_type<>
expected<>: Allows to in-place-construct unexpected_type<>
expected<>: Allows to copy-assign from expected<>
expected<>: Allows to move-assign from expected<>
expected<>: Allows to copy-assign from type convertible to value_type
expected<>: Allows to move-assign from type convertible to value_type
expected<>: Allows to be swapped
expected<>: Allows to observe its value via a pointer
expected<>: Allows to observe its value via a pointer to constant
expected<>: Allows to modify its value via a pointer
expected<>: Allows to observe its value via a reference
expected<>: Allows to observe its value via a r-value reference
expected<>: Allows to modify its value via a reference
expected<>: Allows to observe if it contains a value (or error)
expected<>: Allows to observe its value
expected<>: Allows to modify its value
expected<>: Allows to move its value
expected<>: Allows to observe its error
expected<>: Allows to modify its error
expected<>: Allows to move its error
expected<>: Allows to observe its error as unexpected<>
expected<>: Allows to observe its value if available, or obtain a specified value otherwise
expected<>: Allows to move its value if available, or obtain a specified value otherwise
expected<>: Provides relational operators
...

Get A Weekly Email With Trending Projects For These Topics
No Spam. Unsubscribe easily at any time.
C Plus Plus (371,093
Cpp11 (1,700
Header Only (796
No Dependencies (337
Single File (143
Related Projects