Compare commits

...

10 Commits

Author SHA1 Message Date
c60db27762 Fixed misspelled word 'from' 2023-11-09 00:38:43 +01:00
5064a9a28d GHA: Fix osx job (update image) 2023-11-09 00:38:43 +01:00
fe0384baa6 GHA: Update installed packages on containers 2023-11-09 00:38:43 +01:00
76c82e83ae GHA: Fix failing jobs by updating removed images 2023-11-09 00:38:43 +01:00
e59b1bce1d Fix typo in none_t.hpp. Closes #115. 2023-11-09 00:38:43 +01:00
f95fb5dff2 fix docs 2023-11-09 00:38:43 +01:00
7878dec842 document monadic interface 2023-11-09 00:38:43 +01:00
a3abf04548 added deprecation message 2023-11-09 00:38:43 +01:00
9c43ae3612 Use is_same from Boost.TypeTraits.
boost::core::is_same is deprecated, so use the one from Boost.TypeTraits
instead.
2023-11-09 00:38:43 +01:00
def2db7c45 Switch to boost::core::invoke_swap.
boost::swap is deprecated and will be removed. Use boost::core::invoke_swap
as a replacement.
2023-11-09 00:38:43 +01:00
18 changed files with 129 additions and 69 deletions

View File

@ -11,6 +11,13 @@ on:
- fix/**
- pr/**
concurrency:
group: ${{format('{0}:{1}', github.repository, github.ref)}}
cancel-in-progress: true
env:
NET_RETRY_COUNT: 5
jobs:
posix:
strategy:
@ -110,9 +117,10 @@ jobs:
cxxstd: "03,11,14,17"
- name: "TOOLSET=clang COMPILER=clang++ CXXSTD=03,11 Job 7"
buildtype: "boost"
packages: ""
packages: "clang"
packages_to_remove: ""
os: "ubuntu-18.04"
os: "ubuntu-22.04"
container: "ubuntu:18.04"
cxx: "clang++"
sources: ""
llvm_os: ""
@ -202,12 +210,12 @@ jobs:
buildtype: "boost"
packages: "clang-5.0"
packages_to_remove: ""
os: "ubuntu-20.04"
container: "ubuntu:14.04"
os: "ubuntu-22.04"
container: "ubuntu:18.04"
cxx: "clang++-5.0"
sources: ""
llvm_os: "trusty"
llvm_ver: "5.0"
llvm_os: ""
llvm_ver: ""
toolset: "clang"
compiler: "clang++-5.0"
cxxstd: "03,11,14,1z"
@ -222,13 +230,17 @@ jobs:
- name: If running in container, upgrade packages
if: matrix.container != ''
run: |
apt-get -o Acquire::Retries=3 update && DEBIAN_FRONTEND=noninteractive apt-get -y install tzdata && apt-get -o Acquire::Retries=3 install -y sudo software-properties-common wget curl apt-transport-https make apt-file sudo unzip libssl-dev build-essential autotools-dev autoconf automake g++ libc++-helpers python ruby cpio gcc-multilib g++-multilib pkgconf python3 ccache libpython-dev
sudo apt-add-repository ppa:git-core/ppa
sudo apt-get -o Acquire::Retries=3 update && apt-get -o Acquire::Retries=3 -y install git
python_version=$(python3 -c 'import sys; print("{0.major}.{0.minor}".format(sys.version_info))')
sudo wget https://bootstrap.pypa.io/pip/$python_version/get-pip.py
sudo python3 get-pip.py
sudo /usr/local/bin/pip install cmake
if [ -f "/etc/debian_version" ]; then
echo "DEBIAN_FRONTEND=noninteractive" >> $GITHUB_ENV
export DEBIAN_FRONTEND=noninteractive
apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common curl wget apt-transport-https ca-certificates
# Need (newer) git, and the older Ubuntu container may require requesting the key manually using port 80
curl -sSL --retry ${NET_RETRY_COUNT:-5} 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xE1DD270288B4E6030699E45FA1715D88E1DF1F24' | sudo gpg --dearmor > /etc/apt/trusted.gpg.d/git-core_ubuntu_ppa.gpg
for i in {1..${NET_RETRY_COUNT:-3}}; do sudo -E add-apt-repository -y ppa:git-core/ppa && break || sleep 10; done
apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y g++ python libpython-dev git unzip libssl-dev build-essential libc++-helpers gcc-multilib g++-multilib pkgconf ccache
fi
- uses: actions/checkout@v2
@ -316,27 +328,20 @@ jobs:
- name: "TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,1 Job 15"
buildtype: "boost"
packages: ""
os: "macos-10.15"
os: "macos-11"
cxx: "clang++"
sources: ""
llvm_os: ""
llvm_ver: ""
xcode_version: 11.7
toolset: "clang"
compiler: "clang++"
cxxstd: "03,11,14,1z"
cxxstd: "03,11,14,17,2a"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Set DEVELOPER_DIR
if: matrix.xcode_version != ''
run: echo "DEVELOPER_DIR=/Applications/Xcode_${{ matrix.xcode_version }}.app/Contents/Developer" >> $GITHUB_ENV
- name: Test DEVELOPER_DIR
run: echo $DEVELOPER_DIR
- name: "osx"
shell: bash
env:

View File

@ -2,7 +2,7 @@
[quickbook 1.4]
[authors [Cacciola Carballal, Fernando Luis]]
[copyright 2003-2007 Fernando Luis Cacciola Carballal]
[copyright 2014-2022 Andrzej Krzemieński]
[copyright 2014-2023 Andrzej Krzemieński]
[category miscellaneous]
[id optional]
[dirname optional]
@ -80,13 +80,14 @@ This is how you solve it with `boost::optional`:
[include 11_development.qbk]
[include 12_when_to_use.qbk]
[include 13_relational_operators.qbk]
[include 14_io.qbk]
[include 15_optional_references.qbk]
[include 16_in_place_factories.qbk]
[include 17_gotchas.qbk]
[include 18_exception_safety.qbk]
[include 19_type_requirements.qbk]
[include 1A_on_performance.qbk]
[include 14_monadic_interface.qbk]
[include 15_io.qbk]
[include 16_optional_references.qbk]
[include 17_in_place_factories.qbk]
[include 18_gotchas.qbk]
[include 19_exception_safety.qbk]
[include 1A_type_requirements.qbk]
[include 1B_on_performance.qbk]
[endsect]
[section:reference Reference]
[include 21_ref_none.qbk]

View File

@ -0,0 +1,45 @@
[section Monadic interface]
The monadic interface of `optional` allows the application of functions
to optional values without resorting to the usage of explicit `if`-statements.
Function `map` takes a function mapping type `T` onto type `U` and maps an `optional<T>`
onto an `optional<U>` using the provided function.
int length(const string& s){ return s.size(); };
optional<string> null{}, thin{""}, word{"word"};
assert (null.map(length) == none);
assert (thin.map(length) == 0);
assert (word.map(length) == 4);
Function `flat_map` is similar, but it requires the function to return an
`optional<V>` for some type `V`. This `optional<V>` becomes the return type of
`flat_map`.
optional<char> first_char(const string& s) {
if (s.empty()) return none;
else return s[0];
};
optional<string> null{}, thin{""}, word{"word"};
assert (null.flat_map(first_char) == none);
assert (thin.flat_map(first_char) == none);
assert (word.flat_map(first_char) == 'w');
These functions can be combined in one expression reflecting a chain of computations:
auto get_contents(path p) -> optional<string>;
auto trim(string) -> string;
auto length(string) -> int;
auto trimmed_size_of(optional<path> p) -> int
{
return p.flat_map(get_contents)
.map(trim)
.map(length)
.value_or(0);
}
[endsect]

View File

@ -114,7 +114,7 @@
<span class="phrase"><a name="optional.introduction.problem"></a></span><a class="link" href="index.html#optional.introduction.problem">Problem</a>
</h4>
<p>
Suppose we want to read a parameter form a config file which represents some
Suppose we want to read a parameter from a config file which represents some
integral value, let's call it <code class="computeroutput"><span class="string">"MaxValue"</span></code>.
It is possible that this parameter is not specified; such situation is no error.
It is valid to not specify the parameter and in that case the program is supposed

View File

@ -14,6 +14,14 @@
#define BOOST_NONE_T_17SEP2003_HPP
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#if defined (BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_REF_QUALIFIERS) \
|| defined(BOOST_NO_CXX11_LAMBDAS) || defined(BOOST_NO_CXX11_DECLTYPE_N3276) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_NO_CXX11_DEFAULTED_MOVES) || defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Optional 1.83 and will be removed in Boost.Optional 1.86.")
#endif
namespace boost {

View File

@ -17,6 +17,7 @@
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/conditional.hpp>
#include <boost/core/invoke_swap.hpp>
namespace boost {
@ -894,7 +895,7 @@ class optional : public optional_detail::optional_base<T>
BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
{
// allow for Koenig lookup
boost::swap(*this, arg);
boost::core::invoke_swap(*this, arg);
}

View File

@ -13,7 +13,7 @@
#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP
#include <boost/core/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/optional/optional_fwd.hpp>
namespace boost {
@ -39,8 +39,8 @@ struct swap_selector<true>
else if ( !hasY )
y.emplace();
// Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
boost::swap(x.get(), y.get());
// Boost.Core.Swap will take care of ADL and workarounds for broken compilers
boost::core::invoke_swap(x.get(), y.get());
if( !hasX )
y = boost::none ;
@ -64,13 +64,13 @@ struct swap_selector<false>
{
template <class T>
static void optional_swap ( optional<T>& x, optional<T>& y )
//BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
//BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::core::invoke_swap(*x, *y)))
{
if (x)
{
if (y)
{
boost::swap(*x, *y);
boost::core::invoke_swap(*x, *y);
}
else
{
@ -105,7 +105,7 @@ struct optional_swap_should_use_default_constructor : has_nothrow_default_constr
template <class T>
inline void swap ( optional<T>& x, optional<T>& y )
//BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
//BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::core::invoke_swap(*x, *y)))
{
optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
}

View File

@ -30,7 +30,7 @@
#include <boost/core/addressof.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/core/explicit_operator_bool.hpp>
#include <boost/core/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/optional/bad_optional_access.hpp>
#include <boost/static_assert.hpp>
#include <boost/throw_exception.hpp>
@ -1260,7 +1260,7 @@ class optional
BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
{
// allow for Koenig lookup
boost::swap(*this, arg);
boost::core::invoke_swap(*this, arg);
}

View File

@ -16,14 +16,14 @@
#endif
#include "boost/core/ignore_unused.hpp"
#include "boost/core/is_same.hpp"
#include "boost/core/lightweight_test.hpp"
#include "boost/core/lightweight_test_trait.hpp"
#include "boost/type_traits/is_same.hpp"
using boost::optional;
using boost::make_optional;
using boost::core::is_same;
using boost::is_same;
template <typename Expected, typename Deduced>
void verify_type(Deduced)

View File

@ -16,21 +16,21 @@
#endif
#include "boost/core/ignore_unused.hpp"
#include "boost/core/is_same.hpp"
#include "boost/core/lightweight_test.hpp"
#include "boost/core/lightweight_test_trait.hpp"
#include "boost/type_traits/is_same.hpp"
using boost::optional;
using boost::make_optional;
using boost::core::is_same;
using boost::is_same;
template <typename Expected, typename Deduced>
void verify_type(Deduced)
{
BOOST_TEST_TRAIT_TRUE(( is_same<Expected, Deduced> ));
}
#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
struct MoveOnly
{
@ -38,7 +38,7 @@ struct MoveOnly
explicit MoveOnly(int i) : value(i) {}
MoveOnly(MoveOnly && r) : value(r.value) { r.value = 0; }
MoveOnly& operator=(MoveOnly && r) { value = r.value; r.value = 0; return *this; }
private:
MoveOnly(MoveOnly const&);
void operator=(MoveOnly const&);
@ -53,15 +53,15 @@ void test_make_optional_for_move_only_type()
{
verify_type< optional<MoveOnly> >(make_optional(makeMoveOnly(2)));
verify_type< optional<MoveOnly> >(make_optional(true, makeMoveOnly(2)));
optional<MoveOnly> o1 = make_optional(makeMoveOnly(1));
BOOST_TEST (o1);
BOOST_TEST_EQ (1, o1->value);
optional<MoveOnly> o2 = make_optional(true, makeMoveOnly(2));
BOOST_TEST (o2);
BOOST_TEST_EQ (2, o2->value);
optional<MoveOnly> oN = make_optional(false, makeMoveOnly(2));
BOOST_TEST (!oN);
}
@ -73,15 +73,15 @@ void test_make_optional_for_optional()
optional<int> oi;
verify_type< optional< optional<int> > >(make_optional(oi));
verify_type< optional< optional<int> > >(make_optional(true, oi));
optional< optional<int> > ooi = make_optional(oi);
BOOST_TEST (ooi);
BOOST_TEST (!*ooi);
optional< optional<int> > ooT = make_optional(true, oi);
BOOST_TEST (ooT);
BOOST_TEST (!*ooT);
optional< optional<int> > ooF = make_optional(false, oi);
BOOST_TEST (!ooF);
}
@ -90,21 +90,21 @@ void test_nested_make_optional()
{
verify_type< optional< optional<int> > >(make_optional(make_optional(1)));
verify_type< optional< optional<int> > >(make_optional(true, make_optional(true, 2)));
optional< optional<int> > oo1 = make_optional(make_optional(1));
BOOST_TEST (oo1);
BOOST_TEST (*oo1);
BOOST_TEST_EQ (1, **oo1);
optional< optional<int> > oo2 = make_optional(true, make_optional(true, 2));
BOOST_TEST (oo2);
BOOST_TEST (*oo2);
BOOST_TEST_EQ (2, **oo2);
optional< optional<int> > oo3 = make_optional(true, make_optional(false, 3));
BOOST_TEST (oo3);
BOOST_TEST (!*oo3);
optional< optional<int> > oo4 = make_optional(false, make_optional(true, 4));
BOOST_TEST (!oo4);
}

View File

@ -16,29 +16,29 @@
#endif
#include "boost/core/ignore_unused.hpp"
#include "boost/core/is_same.hpp"
#include "boost/core/lightweight_test.hpp"
#include "boost/core/lightweight_test_trait.hpp"
#include "boost/type_traits/is_same.hpp"
using boost::optional;
using boost::make_optional;
using boost::core::is_same;
using boost::is_same;
template <typename Expected, typename Deduced>
void verify_type(Deduced)
{
BOOST_TEST_TRAIT_TRUE(( is_same<Expected, Deduced> ));
}
#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
struct MoveOnly
{
int value;
explicit MoveOnly(int i) : value(i) {}
MoveOnly(MoveOnly && r) : value(r.value) { r.value = 0; }
MoveOnly& operator=(MoveOnly && r) { value = r.value; r.value = 0; return *this; }
private:
MoveOnly(MoveOnly const&);
void operator=(MoveOnly const&);
@ -70,7 +70,7 @@ void test_map_move_only()
optional<int> oj = makeOptMoveOnly(4).map(get_val);
BOOST_TEST(bool(oj));
BOOST_TEST_EQ(4, *oj);
optional<MoveOnly> o_;
optional<int> oi_ = boost::move(o_).map(get_val);
BOOST_TEST(!oi_);
@ -126,16 +126,16 @@ void test_map_optional()
optional<int> o9 (9), o0 (0), o_;
verify_type<optional<optional<Int> > >(o9.map(make_opt_int));
optional<optional<Int> > oo9 = o9.map(make_opt_int);
BOOST_TEST(bool(oo9));
BOOST_TEST(bool(*oo9));
BOOST_TEST(bool(oo9));
BOOST_TEST(bool(*oo9));
BOOST_TEST_EQ(9, (**oo9).i);
optional<optional<Int> > oo0 = o0.map(make_opt_int);
BOOST_TEST(bool(oo0));
BOOST_TEST(!*oo0);
BOOST_TEST(bool(oo0));
BOOST_TEST(!*oo0);
optional<optional<Int> > oo_ = o_.map(make_opt_int);
BOOST_TEST(!oo_);
BOOST_TEST(!oo_);
}
void test_map_with_lambda()
@ -178,7 +178,7 @@ void test_map_optional_ref()
int main()
{
#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
test_map_move_only();
#endif
test_map_with_lambda();