Coder Social home page Coder Social logo

optional-lite's Introduction

optional lite - nullable objects for C++98 and later

Language Standard Standard License Build Status Version download

optional lite is a single-file header-only library to represent optional (nullable) objects and pass them by value. The library is a variant of std::optional [1,2] for use with C++98 and later and with Visual C++ 6 (VC6).

Contents

Example usage

#include "optional.hpp"

#include <cstdlib>
#include <iostream>

using nonstd::optional;
using nonstd::nullopt;

optional<int> to_int( char const * const text )
{
    char * pos = NULL;
    const int value = strtol( text, &pos, 0 );

    return pos == text ? nullopt : optional<int>( value );
}

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

    optional<int> oi = to_int( text );

    if ( oi ) std::cout << "'" << text << "' is " << *oi;
    else      std::cout << "'" << text << "' isn't a number";
}

Compile and run

prompt>g++ -Wall -Wextra -std=c++03 -I.. -o to_int.exe to_int.cpp && to_int x1
'x1' isn't a number

In a nutshell

optional lite is a single-file header-only library to represent optional (nullable) objects and pass them by value. The library is a variant of std::optional [1,2] for use with C++98 and later and with Visual C++ 6 (VC6). In turn, std::optional is inspired on Boost.Optional [3].

Features and properties of optional lite are ease of installation (single header), default and explicit construction of an empty optional, construction and assignment from a value that is convertible to the underlying type, copy-construction and copy-assignment from another optional of the same type, testing for the presence of a value, operators for unchecked access to the value (pointer or reference), value() and value_or() for checked access to the value, relational operators, swap() and make_optional() to create an optional of the proper type.

Not provided are reference-type optionals, and C++11 capabilities such as move semantics and in-place construction. optional lite doesn't handle overloaded address of operators.

For more examples, see this answer on StackOverflow [4] and the quick start guide [5] of Boost.Optional (note that its interface differs from optional lite).

License

optional lite uses the Boost Software License.

Dependencies

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

Installation

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

Synopsis

Contents
Types in namespace nonstd
Interface of optional lite
Algorithms for optional lite
Macros to control alignment

Types in namespace nonstd

Purpose Type Object
To be, or not template< typename T >
class optional;
 
Disengaging struct nullopt_t; nullopt_t nullopt;
Error reporting class bad_optional_access;  

Interface of optional lite

Kind Method Result
Construction optional() a nulled object
  optional( nullopt_t ) a nulled object
  optional( value_type const & value ) initialized to value
  optional( optional const & other ) initialized to value of other
Destruction ~optional() destruct current content, if any
Assignment optional & operator=( nullopt_t ) null the object;
destruct current content, if any
  optional & operator=( optional const & rhs ) assign the value of other;
destruct current content, if any
Swap void swap( optional & other ) swap with other
State operator bool() const true if content is present (safe bool idiom)
Content 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
  value_type const & operator *() const the current content (const ref);
must contain value
  value_type & operator *() the current content (non-const ref);
must contain value
  value_type const & value() const the current content (const ref);
throws bad_optional_access if nulled
  value_type & value() the current content (non-const ref);
throws bad_optional_access if nulled
  value_type value_or( value_type const & default_value ) the value, or default_value if nulled
value_type must be copy-constructible

Algorithms for optional lite

Kind Function
Relational operators  
== template< typename T >
bool operator==( optional const & x, optional const & y )
!= template< typename T >
bool operator!=( optional const & x, optional const & y )
< template< typename T >
bool operator<( optional const & x, optional const & y )
> template< typename T >
bool operator>( optional const & x, optional const & y )
<= template< typename T >
bool operator<=( optional const & x, optional const & y )
>= template< typename T >
bool operator>=( optional const & x, optional const & y )
Comparison with nullopt  
== template< typename T >
bool operator==( optional const & x, nullopt_t )
  template< typename T >
bool operator==( nullopt_t, optional const & x )
!= template< typename T >
bool operator!=( optional const & x, nullopt_t )
  template< typename T >
bool operator!=( nullopt_t, optional const & x )
< template< typename T >
bool operator<( optional const &, nullopt_t )
  template< typename T >
bool operator<( nullopt_t, optional const & x )
<= template< typename T >
bool operator<=( optional const & x, nullopt_t )
  template< typename T >
bool operator<=( nullopt_t, optional const & )
> template< typename T >
bool operator>( optional const & x, nullopt_t )
  template< typename T >
bool operator>( nullopt_t, optional const & )
>= template< typename T >
bool operator>=( optional const &, nullopt_t )
  template< typename T >
bool operator>=( nullopt_t, optional const & x )
Comparison with T  
== template< typename T >
bool operator==( optional const & x, const T& v )
  template< typename T >
bool operator==( T const & v, optional const & x )
!= template< typename T >
bool operator!=( optional const & x, const T& v )
  template< typename T >
bool operator!=( T const & v, optional const & x )
< template< typename T >
bool operator<( optional const & x, const T& v )
  template< typename T >
bool operator<( T const & v, optional const & x )
<= template< typename T >
bool operator<=( optional const & x, const T& v )
  template< typename T >
bool operator<=( T const & v, optional const & x )
> template< typename T >
bool operator>( optional const & x, const T& v )
  template< typename T >
bool operator>( T const & v, optional const & x )
>= template< typename T >
bool operator>=( optional const & x, const T& v )
  template< typename T >
bool operator>=( T const & v, optional const & x )
Specialized algorithms  
swap template< typename T >
void swap( optional & x, optional & y )
create template< typename T >
optional make_optional( T const & v )

Macros to control alignment

If optional lite is compiled as C++11 or later, C++11 alignment facilities are used for storage of the underlying object. When compiled as pre-C++11, optional lite tries to determine proper alignment itself. If this doesn't work out, you can control alignment via the following macros. See also section Implementation notes.

-Doptional_FEATURE_MAX_ALIGN_HACK=0
Define this to 1 to use the max align hack for alignment. Default is 0.

-Doptional_FEATURE_ALIGN_AS=pod-type
Define this to the pod-type you want to align to (no default).

-Doptional_FEATURE_ALIGN_AS_FALLBACK=pod-type
Define this to the pod-type to use for alignment if the algorithm of optional lite cannot find a suitable POD type to use for alignment. Default is double.

Comparison of std::optional, optional lite and Boost.Optional

optional lite is inspired on std::optional, which in turn is inspired on Boost.Optional. Here are the significant differences.

Aspect optional optional lite Boost.Optional
Move semantics yes no no
noexcept yes no no
Hash support yes no no
Throwing value accessor yes yes no
Literal type partially no no
In-place construction emplace, tag in_place no utility in_place_factory
Disengaged state tag nullopt nullopt none
optional references no (optionally) no yes
Conversion from optional<U>
to optional<T>
no no yes
Duplicated interface functions 1) no no yes
Explicit convert to ptr (get_ptr) no no yes
  1. is_initialized(), reset(), get().

Reported to work with

optional lite is reported to work with the following compilers:

  • Visual C++ 6 SP6 (VS6), VC10, (VS2010), VC11 (VS2012), VC12 (VS2013), ...
  • GNUC 4.8.1 with -std=c++98, -std=c++03, -std=c++11, -std=c++1y
  • clang 3.4 with -std=c++03, -std=c++11 (on Travis)

Implementation notes

Object allocation and alignment

optional lite reserves POD-type storage for an object of the underlying type inside a union to prevent unwanted construction and uses placement new to construct the object when required. Using non-placement new (malloc) to obtain storage, ensures that the memory is properly aligned for the object's type, whereas that's not the case with placement new.

If you access data that's not properly aligned, it 1) may take longer than when it is properly aligned (on x86 processors), or 2) it may terminate the program immediately (many other processors).

Although the C++ standard does not guarantee that all user-defined types have the alignment of some POD type, in practice it's likely they do [6, part 2].

If optional lite is compiled as C++11 or later, C++11 alignment facilities are used for storage of the underlying object. When compiling as pre-C++11, optional lite tries to determine proper alignment using meta programming. If this doesn't work out, you can control alignment via three macros.

optional lite uses the following rules for alignment:

  1. If the program compiles as C++11 or later, C++11 alignment facilities are used.

  2. If you define -Doptional_FEATURE_MAX_ALIGN_HACK=1 the underlying type is aligned as the most restricted type in struct max_align_t. This potentially wastes many bytes per optional if the actually required alignment is much less, e.g. 24 bytes used instead of the 2 bytes required.

  3. If you define -Doptional_FEATURE_ALIGN_AS=pod-type the underlying type is aligned as pod-type. It's your obligation to specify a type with proper alignment.

  4. If you define -Doptional_FEATURE_ALIGN_AS_FALLBACK=pod-type the fallback type for alignment of rule 5 below becomes pod-type. It's your obligation to specify a type with proper alignment.

  5. At default, optional lite tries to find a POD type with the same alignment as the underlying type.

    The algorithm for alignment of 5. is:

    • Determine the alignment A of the underlying type using alignment_of<>.
    • Find a POD type from the list alignment_types with exactly alignment A.
    • If no such POD type is found, use a type with a relatively strict alignment requirement such as double; this type is specified in optional_FEATURE_ALIGN_AS_FALLBACK (default double).

Note that the algorithm of 5. differs from the one Andrei Alexandrescu uses in [6, part 2].

The class template alignment_of<> is gleaned from Boost.TypeTraits, alignment_of [9]. The storage type storage_t<> is adapted from the one I created for spike-expected, expected lite [11].

For more information on constructed unions and alignment, see [6-10].

Notes and references

[1] Fernando Cacciola, Andrzej Krzemieński. A proposal to add a utility class to represent optional objects (Revision 5).

[2] Andrzej Krzemieński. optional (nullable) objects for C++14. Reference implementation on GitHub.

[3] Fernando Cacciola. Boost.Optional library.

[4] StackOverflow. How should one use std::optional?. Answer by Timothy Shields. 31 May 2013.

[5] Fernando Cacciola. Boost.Optional Quick start guide.

[6] Andrei Alexandrescu. Generic: Discriminated Unions part 1, part 2, part 3. April 2002.

[7] Herb Sutter. Style Case Study #3: Construction Unions. GotW #85. 2009

[8] Kevin T. Manley. Using Constructed Types in C++ Unions. C/C++ Users Journal, 20(8), August 2002.

[9] StackOverflow. Determining maximum possible alignment in C++.

[10] Boost.TypeTraits, alignment_of ( code ).

[11] Martin Moene. spike-expected (expected-lite.hpp).

optional-lite's People

Contributors

martinmoene avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.