blob: a6b2b1314ac251adf6bbcad958cc10ebf6f0afdb [file] [log] [blame]
// 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 BOOST_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 <typename Expected, typename Deduced>
void verify_type(Deduced)
{
BOOST_TEST_TRAIT_TRUE(( is_same<Expected, Deduced> ));
}
struct Int
{
int i;
explicit Int(int i_) : i(i_) {}
};
struct convert_t
{
typedef optional<Int> result_type;
optional<Int> operator()(int i) { if (i != 0) return Int(i); else return boost::none; }
};
void test_flat_map_on_mutable_optional_with_function_object()
{
{
optional<int> oi (1);
verify_type< optional<Int> >(oi.flat_map(convert_t()));
optional<Int> oI = oi.flat_map(convert_t());
BOOST_TEST(bool(oI));
BOOST_TEST_EQ(1, oI->i);
}
{
optional<int> oi (0);
optional<Int> oI = oi.flat_map(convert_t());
BOOST_TEST(!oI);
}
{
optional<int> oi;
optional<Int> oI = oi.flat_map(convert_t());
BOOST_TEST(!oI);
}
}
void test_flat_map_on_const_optional_with_function_object()
{
{
const optional<int> oi (1);
verify_type< optional<Int> >(oi.flat_map(convert_t()));
optional<Int> oI = oi.flat_map(convert_t());
BOOST_TEST(bool(oI));
BOOST_TEST_EQ(1, oI->i);
}
{
const optional<int> oi (0);
optional<Int> oI = oi.flat_map(convert_t());
BOOST_TEST(!oI);
}
{
const optional<int> oi;
optional<Int> oI = oi.flat_map(convert_t());
BOOST_TEST(!oI);
}
}
void test_flat_map_with_lambda()
{
#if !defined BOOST_NO_CXX11_LAMBDAS && !defined BOOST_NO_CXX11_DECLTYPE_N3276
{
optional<int> oi (1);
verify_type< optional<Int> >(oi.flat_map([](int i){ return optional<Int>(i == 0, Int(i)); }));
optional<Int> oI = oi.flat_map([](int i){ return optional<Int>(i != 0, Int(i)); });
BOOST_TEST(bool(oI));
BOOST_TEST_EQ(1, oI->i);
}
{
optional<int> oi (0);
optional<Int> oI = oi.flat_map([](int i){ return optional<Int>(i != 0, Int(i)); });
BOOST_TEST(!oI);
}
{
optional<int> oi;
optional<Int> oI = oi.flat_map([](int i){ return optional<Int>(i != 0, Int(i)); });
BOOST_TEST(!oI);
}
#endif // lambdas
}
struct get_opt_ref
{
typedef optional<int&> result_type;
optional<int&> operator()(int& i) { return i != 0 ? optional<int&>(i) : optional<int&>(); }
};
void test_flat_map_obj_to_ref()
{
{
optional<int> oi (2);
verify_type< optional<int&> >(oi.flat_map(get_opt_ref()));
optional<int&> ori = oi.flat_map(get_opt_ref());
BOOST_TEST(bool(ori));
BOOST_TEST_EQ(2, *ori);
*ori = 3;
BOOST_TEST(bool(oi));
BOOST_TEST_EQ(3, *oi);
BOOST_TEST_EQ(3, *ori);
}
{
optional<int> oi (0);
optional<int&> ori = oi.flat_map(get_opt_ref());
BOOST_TEST(!ori);
}
{
optional<int> oi;
optional<int&> ori = oi.flat_map(get_opt_ref());
BOOST_TEST(!ori);
}
}
optional<int&> get_opt_int_ref(Int& i)
{
return i.i ? optional<int&>(i.i) : optional<int&>();
}
void test_flat_map_ref_to_ref()
{
{
Int I (5);
optional<Int&> orI (I);
verify_type< optional<int&> >(orI.flat_map(get_opt_int_ref));
optional<int&> ori = orI.flat_map(get_opt_int_ref);
BOOST_TEST(bool(ori));
BOOST_TEST_EQ(5, *ori);
*ori = 6;
BOOST_TEST_EQ(6, *ori);
BOOST_TEST_EQ(6, I.i);
}
{
Int I (0);
optional<Int&> orI (I);
optional<int&> ori = orI.flat_map(get_opt_int_ref);
BOOST_TEST(!ori);
}
{
optional<Int&> orI;
optional<int&> ori = orI.flat_map(get_opt_int_ref);
BOOST_TEST(!ori);
}
}
optional< optional<Int> > make_opt_int(int i)
{
if (i == 0)
return boost::none;
else if (i == 1)
return boost::make_optional(optional<Int>());
else
return boost::make_optional(boost::make_optional(Int(i)));
}
void test_flat_map_opt_opt()
{
{
optional<int> oi (9);
verify_type<optional<optional<Int> > >(oi.flat_map(make_opt_int));
optional<optional<Int> > ooI = oi.flat_map(make_opt_int);
BOOST_TEST(bool(ooI));
BOOST_TEST(bool(*ooI));
BOOST_TEST_EQ(9, (**ooI).i);
}
{
optional<int> oi (1);
optional<optional<Int> > ooI = oi.flat_map(make_opt_int);
BOOST_TEST(bool(ooI));
BOOST_TEST(!*ooI);
}
{
optional<int> oi (0);
optional<optional<Int> > ooI = oi.flat_map(make_opt_int);
BOOST_TEST(!ooI);
}
{
optional<int> oi;
optional<optional<Int> > ooI = oi.flat_map(make_opt_int);
BOOST_TEST(!ooI);
}
}
#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<MoveOnly> makeOptMoveOnly(int i)
{
return optional<MoveOnly>(MoveOnly(i));
}
optional<int> get_val(MoveOnly m)
{
return optional<int>(m.value != 0, m.value);
}
void test_flat_map_move_only()
{
{
optional<MoveOnly> om (makeMoveOnly(1)), om2 (makeMoveOnly(2));
verify_type<optional<int> >(boost::move(om).flat_map(get_val));
optional<int> oi = boost::move(om2).flat_map(get_val);
BOOST_TEST(bool(oi));
BOOST_TEST_EQ(2, *oi);
}
{
optional<int> oj = makeOptMoveOnly(4).flat_map(get_val);
BOOST_TEST(bool(oj));
BOOST_TEST_EQ(4, *oj);
}
{
optional<int> oj = optional<MoveOnly>().flat_map(get_val);
BOOST_TEST(!oj);
}
}
#endif // no rvalue refs
int main()
{
test_flat_map_on_mutable_optional_with_function_object();
test_flat_map_on_const_optional_with_function_object();
test_flat_map_with_lambda();
test_flat_map_obj_to_ref();
test_flat_map_ref_to_ref();
test_flat_map_opt_opt();
#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
test_flat_map_move_only();
#endif
return boost::report_errors();
}