276 lines
6.4 KiB
C++
276 lines
6.4 KiB
C++
// 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 <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();
|
|
}
|