// Copyright (C) 2018 Andrzej Krzemienski. // // Use, modification, and distribution is subject to 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) // // See http://www.boost.org/lib/optional for documentation. // // You are welcome to contact the author at: // akrzemi1@gmail.com #include "boost/optional/optional.hpp" #ifdef __BORLANDC__ #pragma hdrstop #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" using boost::optional; using boost::make_optional; using boost::core::is_same; template void verify_type(Deduced) { BOOST_TEST_TRAIT_TRUE(( is_same )); } #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&); }; MoveOnly makeMoveOnly(int i) { return MoveOnly(i); } optional makeOptMoveOnly(int i) { return optional(MoveOnly(i)); } int get_val(MoveOnly m) { return m.value; } void test_map_move_only() { optional om (makeMoveOnly(7)), om2 (makeMoveOnly(8)); verify_type >(boost::move(om).map(get_val)); optional oi = boost::move(om2).map(get_val); BOOST_TEST(bool(oi)); BOOST_TEST_EQ(8, *oi); optional oj = makeOptMoveOnly(4).map(get_val); BOOST_TEST(bool(oj)); BOOST_TEST_EQ(4, *oj); optional o_; optional oi_ = boost::move(o_).map(get_val); BOOST_TEST(!oi_); } #endif // no rvalue refs struct Int { int i; explicit Int(int i_) : i(i_) {} }; struct convert_t { typedef Int result_type; Int operator()(int i) { return Int(i); } }; int& get_int_ref(Int& i) { return i.i; } struct get_ref { typedef int& result_type; int& operator()(int& i) { return i; } }; void test_map() { optional oi (1); verify_type >(oi.map(convert_t())); optional oI = oi.map(convert_t()); BOOST_TEST(bool(oI)); BOOST_TEST_EQ(1, oI->i); optional o_ = optional().map(convert_t()); BOOST_TEST(!o_); } optional make_opt_int(int i) { if (i != 0) return Int(i); else return boost::none; } void test_map_optional() { optional o9 (9), o0 (0), o_; verify_type > >(o9.map(make_opt_int)); optional > oo9 = o9.map(make_opt_int); BOOST_TEST(bool(oo9)); BOOST_TEST(bool(*oo9)); BOOST_TEST_EQ(9, (**oo9).i); optional > oo0 = o0.map(make_opt_int); BOOST_TEST(bool(oo0)); BOOST_TEST(!*oo0); optional > oo_ = o_.map(make_opt_int); BOOST_TEST(!oo_); } void test_map_with_lambda() { #if !defined BOOST_NO_CXX11_LAMBDAS && !defined BOOST_NO_CXX11_DECLTYPE_N3276 optional oi (1), oj(2); verify_type >(oi.map([](int i){ return i == 1; })); optional ob = oi.map([](int i){ return i == 1; }); optional oc = oj.map([](int i){ return i == 1; }); BOOST_TEST(bool(ob)); BOOST_TEST_EQ(true, *ob); BOOST_TEST(bool(oc)); BOOST_TEST_EQ(false, *oc); #endif // lambdas } void test_map_to_ref() { optional oi (2); verify_type >(oi.map(get_ref())); optional ori = oi.map(get_ref()); BOOST_TEST(bool(ori)); *ori = 3; BOOST_TEST(bool(oi)); BOOST_TEST_EQ(3, *oi); BOOST_TEST_EQ(3, *ori); } void test_map_optional_ref() { Int I (5); optional ori (I); verify_type >(ori.map(get_int_ref)); optional orii = ori.map(get_int_ref); BOOST_TEST(bool(orii)); BOOST_TEST_EQ(5, *orii); *orii = 6; BOOST_TEST_EQ(6, I.i); } int main() { #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) test_map_move_only(); #endif test_map_with_lambda(); test_map(); test_map_optional(); test_map_to_ref(); test_map_optional(); test_map_optional_ref(); return boost::report_errors(); }