Skip to content

Commit

Permalink
Release 2.3.0, use std::optional if available
Browse files Browse the repository at this point in the history
  • Loading branch information
martinmoene committed Dec 10, 2017
1 parent b33056c commit b2d3d63
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 12 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
optional lite - A single-file header-only version of a C++17-like optional, a nullable object for C++98, C++11 and later
====================================================
[![Language](https://img.shields.io/badge/language-C++-blue.svg)](https://isocpp.org/) [![Standard](https://img.shields.io/badge/c%2B%2B-98/11-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Build Status](https://travis-ci.org/martinmoene/optional-lite.svg?branch=master)](https://travis-ci.org/martinmoene/optional-lite) [![Build status](https://ci.appveyor.com/api/projects/status/1oq5gjm7bufrv6ib?svg=true)](https://ci.appveyor.com/project/martinmoene/optional-lite) [![Version](https://badge.fury.io/gh/martinmoene%2Foptional-lite.svg)](https://github.com/martinmoene/optional-lite/releases) [![download](https://img.shields.io/badge/latest-download-blue.svg)](https://raw.githubusercontent.com/martinmoene/optional-lite/master/include/nonstd/optional.hpp) [![Conan](https://img.shields.io/badge/conan-download-blue.svg)](https://bintray.com/agauniyal/nonstd-lite/optional-lite%3Anonstd-lite/_latestVersion) [![Try it online](https://img.shields.io/badge/try%20it-online-blue.svg)](https://wandbox.org/permlink/4gJ5Yhyv0bwzJ5x8)
[![Language](https://img.shields.io/badge/language-C++-blue.svg)](https://isocpp.org/) [![Standard](https://img.shields.io/badge/c%2B%2B-98/11-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Build Status](https://travis-ci.org/martinmoene/optional-lite.svg?branch=master)](https://travis-ci.org/martinmoene/optional-lite) [![Build status](https://ci.appveyor.com/api/projects/status/1oq5gjm7bufrv6ib?svg=true)](https://ci.appveyor.com/project/martinmoene/optional-lite) [![Version](https://badge.fury.io/gh/martinmoene%2Foptional-lite.svg)](https://github.com/martinmoene/optional-lite/releases) [![download](https://img.shields.io/badge/latest-download-blue.svg)](https://raw.githubusercontent.com/martinmoene/optional-lite/master/include/nonstd/optional.hpp) [![Conan](https://img.shields.io/badge/conan-download-blue.svg)](https://bintray.com/agauniyal/nonstd-lite/optional-lite%3Anonstd-lite/_latestVersion) [![Try it online](https://img.shields.io/badge/try%20it-online-blue.svg)](https://wandbox.org/permlink/DMZg1wOekSwEb54i)

**Contents**
- [Example usage](#example-usage)
Expand Down Expand Up @@ -56,7 +56,7 @@ prompt>g++ -Wall -Wextra -std=c++03 -I.. -o to_int.exe to_int.cpp && to_int x1
In a nutshell
---------------
**optional lite** is a single-file header-only library to represent optional (nullable) objects and pass them by value. The library aims to provide a [C++17-like optional](http://en.cppreference.com/w/cpp/utility/optional) for use with C++98 and later. There's also a simpler version, [*optional bare*](https://github.com/martinmoene/optional-bare). Unlike *optional lite*, *optional bare* is limited to default-constructible and copyable types.
**optional lite** is a single-file header-only library to represent optional (nullable) objects and pass them by value. The library aims to provide a [C++17-like optional](http://en.cppreference.com/w/cpp/utility/optional) for use with C++98 and later. If available, std::optional is used. There's also a simpler version, [*optional bare*](https://github.com/martinmoene/optional-bare). Unlike *optional lite*, *optional bare* is limited to default-constructible and copyable types.
**Features and properties of optional lite** are ease of installation (single header), freedom of dependencies other than the standard library and control over object alignment (if needed). *optional lite* shares the approach to in-place tags with [any-lite](https://github.com/martinmoene/any-lite) and with [variant-lite](https://github.com/martinmoene/variant-lite) and these libraries can be used together.
Expand Down
72 changes: 63 additions & 9 deletions include/nonstd/optional.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (c) 2016 Martin Moene
// Copyright (c) 2014-2017 Martin Moene
//
// https://github.com/martinmoene/optional-lite
//
Expand All @@ -18,12 +18,58 @@
#ifndef NONSTD_OPTIONAL_LITE_HPP
#define NONSTD_OPTIONAL_LITE_HPP

#define optional_lite_VERSION "2.3.0"

// Compiler detection:

#define optional_CPP11_OR_GREATER ( __cplusplus >= 201103L )
#define optional_CPP14_OR_GREATER ( __cplusplus >= 201402L )
#define optional_CPP17_OR_GREATER ( __cplusplus >= 201703L )

// use C++17 std::optional if available:

#if defined( __has_include )
# define optional_HAS_INCLUDE( arg ) __has_include( arg )
#else
# define optional_HAS_INCLUDE( arg ) 0
#endif

#if optional_HAS_INCLUDE( <optional> ) && optional_CPP17_OR_GREATER

#define optional_HAVE_STD_OPTIONAL 1

#include <optional>

namespace nonstd {

using std::optional;
using std::bad_optional_access;
using std::hash;

using std::nullopt;
using std::in_place;
using std::in_place_type;
using std::in_place_index;
using std::in_place_t;
using std::in_place_type_t;
using std::in_place_index_t;

using std::operator==;
using std::operator!=;
using std::operator<;
using std::operator<=;
using std::operator>;
using std::operator>=;
using std::make_optional;
using std::swap;
}

#else // C++17 std::optional

#include <cassert>
#include <stdexcept>
#include <utility>

#define optional_lite_VERSION "2.2.1"

// optional-lite alignment configuration:

#ifndef optional_CONFIG_MAX_ALIGN_HACK
Expand All @@ -38,12 +84,6 @@
# define optional_CONFIG_ALIGN_AS_FALLBACK double
#endif

// Compiler detection (C++17 is speculative):

#define optional_CPP11_OR_GREATER ( __cplusplus >= 201103L )
#define optional_CPP14_OR_GREATER ( __cplusplus >= 201402L )
#define optional_CPP17_OR_GREATER ( __cplusplus >= 201700L )

// half-open range [lo..hi):
#define optional_BETWEEN( v, lo, hi ) ( lo <= v && v < hi )

Expand Down Expand Up @@ -226,6 +266,18 @@ inline in_place_t in_place( detail::in_place_index_tag<I> = detail::in_place_ind
return in_place_t();
}

template< class T >
inline in_place_t in_place_type( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
{
return in_place_t();
}

template< std::size_t I >
inline in_place_t in_place_index( detail::in_place_index_tag<I> = detail::in_place_index_tag<I>() )
{
return in_place_t();
}

// mimic templated typedef:

#define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
Expand Down Expand Up @@ -1114,4 +1166,6 @@ struct hash< nonstd::optional<T> >

#endif // optional_CPP11_OR_GREATER

#endif // have C++17 std::optional

#endif // NONSTD_OPTIONAL_LITE_HPP
28 changes: 27 additions & 1 deletion test/optional.t.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2014-2016 by Martin Moene
// Copyright 2014-2017 by Martin Moene
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Expand Down Expand Up @@ -249,7 +249,11 @@ CASE( "optional: Allows to in-place copy-construct from value (C++11)" )

EXPECT( a->first == 'a' );
EXPECT( a->second.value == 7 );
#if optional_HAVE_STD_OPTIONAL
EXPECT( a->second.state == copy_constructed );
#else
EXPECT( a->second.state == move_constructed );
#endif
EXPECT( s.state != moved_from );
#else
EXPECT( !!"optional: in-place construction is not available (no C++11)" );
Expand Down Expand Up @@ -284,7 +288,11 @@ CASE( "optional: Allows to in-place copy-construct from initializer-list (C++11)
EXPECT( a->vec[2] == 9 );
EXPECT( a->c == 'a');
EXPECT( a->s.value == 7 );
#if optional_HAVE_STD_OPTIONAL
EXPECT( a->s.state == copy_constructed );
#else
EXPECT( a->s.state == move_constructed );
#endif
EXPECT( s.state != moved_from );
#else
EXPECT( !!"optional: in-place construction is not available (no C++11)" );
Expand Down Expand Up @@ -402,7 +410,11 @@ CASE( "optional: Allows to copy-emplace content from arguments (C++11)" )

EXPECT( a->first == 'a' );
EXPECT( a->second.value == 7 );
#if optional_HAVE_STD_OPTIONAL
EXPECT( a->second.state == copy_constructed );
#else
EXPECT( a->second.state == move_constructed );
#endif
EXPECT( s.state != moved_from );
#else
EXPECT( !!"optional: in-place construction is not available (no C++11)" );
Expand Down Expand Up @@ -440,7 +452,11 @@ CASE( "optional: Allows to copy-emplace content from intializer-list and argumen
EXPECT( a->vec[2] == 9 );
EXPECT( a->c == 'a' );
EXPECT( a->s.value == 7 );
#if optional_HAVE_STD_OPTIONAL
EXPECT( a->s.state == copy_constructed );
#else
EXPECT( a->s.state == move_constructed );
#endif
EXPECT( s.state != moved_from );
#else
EXPECT( !!"optional: in-place construction is not available (no C++11)" );
Expand Down Expand Up @@ -734,7 +750,11 @@ CASE( "make_optional: Allows to in-place copy-construct optional from arguments

EXPECT( a->first == 'a' );
EXPECT( a->second.value == 7 );
#if optional_HAVE_STD_OPTIONAL
EXPECT( a->second.state == copy_constructed );
#else
EXPECT( a->second.state == move_constructed );
#endif
EXPECT( s.state != moved_from );
#else
EXPECT( !!"optional: in-place construction is not available (no C++11)" );
Expand Down Expand Up @@ -769,7 +789,11 @@ CASE( "make_optional: Allows to in-place copy-construct optional from initialize
EXPECT( a->vec[2] == 9 );
EXPECT( a->c == 'a' );
EXPECT( a->s.value == 7 );
#if optional_HAVE_STD_OPTIONAL
EXPECT( a->s.state == copy_constructed );
#else
EXPECT( a->s.state == move_constructed );
#endif
EXPECT( s.state != moved_from );
#else
EXPECT( !!"optional: in-place construction is not available (no C++11)" );
Expand Down Expand Up @@ -841,8 +865,10 @@ CASE("storage_t: Show sizeof various optionals"
"[.]" )
{
std::cout <<
#ifndef optional_HAVE_STD_OPTIONAL
"sizeof( nonstd::optional_lite::detail::storage_t<char> ): " <<
sizeof( nonstd::optional_lite::detail::storage_t<char> ) << "\n" <<
#endif
optional_OUTPUT_SIZEOF( char )
optional_OUTPUT_SIZEOF( short )
optional_OUTPUT_SIZEOF( int )
Expand Down

0 comments on commit b2d3d63

Please sign in to comment.