Skip to content

Commit

Permalink
More make_unbounded_variant
Browse files Browse the repository at this point in the history
  • Loading branch information
serges147 committed Jun 5, 2024
1 parent 6192ecb commit 634fc25
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 23 deletions.
48 changes: 48 additions & 0 deletions cetlvast/suites/unittest/test_unbounded_variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1646,6 +1646,54 @@ TEST_F(TestPmrUnboundedVariant, pmr_reset_memory_resource)
EXPECT_THAT(a.get_memory_resource(), get_default_mr());
}

TEST_F(TestPmrUnboundedVariant, pmr_make_unbounded_variant_cppref_example)
{
using ub_var = unbounded_variant<0, true, true, alignof(std::max_align_t), pmr>;

auto a0 = make_unbounded_variant<std::string, ub_var>(get_mr(), "Hello, cetl::unbounded_variant!\n");
auto a1 = make_unbounded_variant<std::complex<double>, ub_var>(get_mr(), 0.1, 2.3);

EXPECT_THAT(get<std::string>(a0), "Hello, cetl::unbounded_variant!\n");
EXPECT_THAT(get<std::complex<double>>(a1), std::complex<double>(0.1, 2.3));

using lambda = std::function<const char*()>;
using ub_var_lambda = cetl::unbounded_variant<0, true, true, alignof(std::max_align_t), pmr>;

auto a3 = make_unbounded_variant<lambda, ub_var_lambda>(get_mr(), [] { return "Lambda #3.\n"; });
EXPECT_TRUE(a3.has_value());
EXPECT_THAT(get<lambda>(a3)(), "Lambda #3.\n");
}

TEST_F(TestPmrUnboundedVariant, pmr_make_unbounded_variant_1)
{
using ub_var = unbounded_variant<sizeof(int), false, true, 16, pmr>;

auto src = make_unbounded_variant<int, ub_var>(get_mr(), 42);
EXPECT_THAT(get<int>(src), 42);
static_assert(std::is_same<decltype(src), ub_var>::value, "");
}

TEST_F(TestPmrUnboundedVariant, pmr_make_unbounded_variant_2_list)
{
struct MyType : rtti_helper<type_id_type<13>>
{
std::size_t size_;
int number_;

MyType(const std::initializer_list<char> chars, const int number)
{
size_ = chars.size();
number_ = number;
}
};
using ub_var = unbounded_variant<sizeof(MyType), true, true, alignof(std::max_align_t), pmr>;

const auto src = make_unbounded_variant<MyType, ub_var>(get_mr(), {'A', 'C'}, 42);
const auto& test = get<const MyType&>(src);
EXPECT_THAT(test.size_, 2);
EXPECT_THAT(test.number_, 42);
}

} // namespace

namespace cetl
Expand Down
122 changes: 99 additions & 23 deletions include/cetl/unbounded_variant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -994,13 +994,21 @@ class unbounded_variant : detail::base_move<Pmr, Footprint, Copyable, Movable, A
struct is_in_place_type;

public:
/// Type of the Polymorphic Memory Resource (PMR) used by the variant.
///
/// `void` if PMR support is disabled.
///
using PmrType = Pmr;
using IsPmr = detail::IsPmr<Pmr>;

using base::reset;
using base::has_value;
using base::valueless_by_exception;

/// Implementation similar to \ref std::in_place_type_t or \ref cetl::pf17::in_place_type_t.
///
/// In use by several \ref cetl::unbounded_variant constructors.
/// In use by several \ref cetl::unbounded_variant constructors,
/// but please consider using \ref cetl::make_unbounded_variant instead.
///
/// Can't use directly either of already existing `std::in_place_type_t` or `cetl::pf17::in_place_type_t` types due
/// to C++14 limitation and polyfill optionality (by design in CETL, according to Scott), so a bit of code
Expand All @@ -1014,8 +1022,6 @@ class unbounded_variant : detail::base_move<Pmr, Footprint, Copyable, Movable, A

/// \brief Constructs an empty `unbounded_variant` object.
///
/// In case of enabled PMR support, the default memory resource is used.
///
template <typename PmrAlias = Pmr, typename = detail::EnableIfNotPmrT<PmrAlias>>
unbounded_variant()
{
Expand Down Expand Up @@ -1047,12 +1053,9 @@ class unbounded_variant : detail::base_move<Pmr, Footprint, Copyable, Movable, A

/// \brief Constructs an `unbounded_variant` object by forwarding a value into variant's storage.
///
/// Size of the value must be less than or equal to `Footprint` to benefit small object optimization,
/// and it can't be bigger than `Footprint` in case of disabled PMR support.
/// Size of the value must be less than or equal to `Footprint`.
/// Any failure during the value forwarding will result in the "valueless by exception" state.
///
/// In case of enabled PMR support, the default memory resource is used.
///
/// \tparam ValueType Type of the value to be stored.
/// Its size must be less than or equal to `Footprint` in case of PMR support.
/// \param value Value to be stored.
Expand Down Expand Up @@ -1092,11 +1095,10 @@ class unbounded_variant : detail::base_move<Pmr, Footprint, Copyable, Movable, A

/// \brief Constructs an `unbounded_variant` object with in place constructed value.
///
/// Size of the value must be less than or equal to `Footprint` to benefit small object optimization,
/// and it can't be bigger than `Footprint` in case of PMR support is disabled.
/// Any failure during the construction will result in the "valueless by exception" state.
/// Please consider using \ref cetl::make_unbounded_variant helper instead.
///
/// In case of enabled PMR support, the default memory resource is used.
/// Size of the value must be less than or equal to `Footprint`.
/// Any failure during the construction will result in the "valueless by exception" state.
///
/// \tparam ValueType Type of the value to be stored.
/// \tparam Args Types of arguments to be passed to the constructor of `ValueType`.
Expand All @@ -1112,7 +1114,9 @@ class unbounded_variant : detail::base_move<Pmr, Footprint, Copyable, Movable, A
create<Tp>(std::forward<Args>(args)...);
}

/// \brief Constructs an `unbounded_variant` object with in place constructed value.
/// \brief Constructs a PMR-enabled `unbounded_variant` object with in place constructed value.
///
/// Please consider using \ref cetl::make_unbounded_variant helper instead.
///
/// Size of the value must be less than or equal to `Footprint` to benefit small object optimization,
/// otherwise the value will be stored into PMR allocated storage.
Expand All @@ -1136,11 +1140,10 @@ class unbounded_variant : detail::base_move<Pmr, Footprint, Copyable, Movable, A

/// \brief Constructs an `unbounded_variant` object with in place constructed value and initializer list.
///
/// Size of the value must be less than or equal to `Footprint` to benefit small object optimization,
/// and it can't be bigger than `Footprint` in case of PMR support is disabled.
/// Any failure during the construction will result in the "valueless by exception" state.
/// Please consider using \ref cetl::make_unbounded_variant helper instead.
///
/// In case of enabled PMR support, the default memory resource is used.
/// Size of the value must be less than or equal to `Footprint`.
/// Any failure during the construction will result in the "valueless by exception" state.
///
/// \tparam ValueType Type of the value to be stored. Its size must be less than or equal to `Footprint`.
/// \tparam Up Type of the elements of the initializer list.
Expand All @@ -1159,7 +1162,7 @@ class unbounded_variant : detail::base_move<Pmr, Footprint, Copyable, Movable, A
create<Tp>(list, std::forward<Args>(args)...);
}

/// \brief Constructs an `unbounded_variant` object with in place constructed value and initializer list.
/// \brief Constructs a PMR-enabled `unbounded_variant` object with in place constructed value and initializer list.
///
/// Size of the value must be less than or equal to `Footprint` to benefit small object optimization,
/// otherwise the value will be stored into PMR allocated storage.
Expand Down Expand Up @@ -1472,29 +1475,102 @@ using unbounded_variant_like = unbounded_variant<sizeof(ValueType),
std::is_move_constructible<ValueType>::value,
alignof(ValueType)>;

/// \brief Constructs an unbounded_variant object containing an object of type T,
/// passing the provided arguments to T's constructor.
/// \brief Makes an `unbounded_variant` object with in place constructed value.
///
/// Size of the value must be less than or equal to `Footprint`.
/// Any failure during the construction will result in the "valueless by exception" state.
///
/// \tparam ValueType Type of the value to be stored. Its size must be less than or equal to `Footprint`.
/// \tparam UnboundedVariant Template type of the result unbounded variant.
/// \tparam Args Types of arguments to be passed to the constructor of `ValueType`.
/// \param args Arguments to be forwarded to the constructor of `ValueType`.
///
template <typename ValueType, typename UnboundedVariant = unbounded_variant_like<ValueType>, typename... Args>
template <typename ValueType,
typename UnboundedVariant = unbounded_variant_like<ValueType>,
typename... Args,
typename = std::enable_if_t<!UnboundedVariant::IsPmr::value>>
CETL_NODISCARD UnboundedVariant make_unbounded_variant(Args&&... args)
{
using in_place_type_t = typename UnboundedVariant::template in_place_type_t<ValueType>;
return UnboundedVariant(in_place_type_t{}, std::forward<Args>(args)...);
}

/// \brief Constructs an unbounded_variant object containing an object of type T,
/// passing the provided arguments to T's constructor.
/// \brief Makes an `unbounded_variant` object with in place constructed value and initializer list.
///
/// Size of the value must be less than or equal to `Footprint`.
/// Any failure during the construction will result in the "valueless by exception" state.
///
/// \tparam ValueType Type of the value to be stored. Its size must be less than or equal to `Footprint`.
/// \tparam UnboundedVariant Template type of the result unbounded variant.
/// \tparam Up Type of the elements of the initializer list.
/// \tparam Args Types of arguments to be passed to the constructor of `ValueType`.
/// \param mem_res Pointer to a memory resource to be used by the variant.
/// \param list Initializer list to be forwarded to the constructor of `ValueType`.
/// \param args Arguments to be forwarded to the constructor of `ValueType`.
///
template <typename ValueType,
typename UnboundedVariant = unbounded_variant_like<ValueType>,
typename Up,
typename... Args>
typename... Args,
typename = std::enable_if_t<!UnboundedVariant::IsPmr::value>>
CETL_NODISCARD UnboundedVariant make_unbounded_variant(std::initializer_list<Up> list, Args&&... args)
{
using in_place_type_t = typename UnboundedVariant::template in_place_type_t<ValueType>;
return UnboundedVariant(in_place_type_t{}, list, std::forward<Args>(args)...);
}

/// \brief Makes a PMR-enabled `unbounded_variant` object with in place constructed value.
///
/// Size of the value must be less than or equal to `Footprint` to benefit small object optimization,
/// otherwise the value will be stored into PMR allocated storage.
/// Any failure during the construction will result in the "valueless by exception" state.
///
/// \tparam ValueType Type of the value to be stored. Its size must be less than or equal to `Footprint`.
/// \tparam UnboundedVariant Template type of the result unbounded variant.
/// \tparam Args Types of arguments to be passed to the constructor of `ValueType`.
/// \param mem_res Pointer to a memory resource to be used by the variant.
/// \param list Initializer list to be forwarded to the constructor of `ValueType`.
/// \param args Arguments to be forwarded to the constructor of `ValueType`.
///
template <typename ValueType,
typename UnboundedVariant = unbounded_variant_like<ValueType>,
typename... Args,
typename Pmr = typename UnboundedVariant::PmrType,
typename = std::enable_if_t<UnboundedVariant::IsPmr::value>>
CETL_NODISCARD UnboundedVariant make_unbounded_variant(Pmr* const mem_res, Args&&... args)
{
using in_place_type_t = typename UnboundedVariant::template in_place_type_t<ValueType>;
return UnboundedVariant(mem_res, in_place_type_t{}, std::forward<Args>(args)...);
}

/// \brief Makes a PMR-enabled `unbounded_variant` object with in place constructed value and initializer list.
///
/// Size of the value must be less than or equal to `Footprint` to benefit small object optimization,
/// otherwise the value will be stored into PMR allocated storage.
/// Any failure during the construction will result in the "valueless by exception" state.
///
/// \tparam ValueType Type of the value to be stored. Its size must be less than or equal to `Footprint`.
/// \tparam UnboundedVariant Template type of the result unbounded variant.
/// \tparam Up Type of the elements of the initializer list.
/// \tparam Args Types of arguments to be passed to the constructor of `ValueType`.
/// \param mem_res Pointer to a memory resource to be used by the variant.
/// \param list Initializer list to be forwarded to the constructor of `ValueType`.
/// \param args Arguments to be forwarded to the constructor of `ValueType`.
///
template <typename ValueType,
typename UnboundedVariant = unbounded_variant_like<ValueType>,
typename Up,
typename... Args,
typename Pmr = typename UnboundedVariant::PmrType,
typename = std::enable_if_t<UnboundedVariant::IsPmr::value>>
CETL_NODISCARD UnboundedVariant make_unbounded_variant(Pmr* const mem_res,
std::initializer_list<Up> list,
Args&&... args)
{
using in_place_type_t = typename UnboundedVariant::template in_place_type_t<ValueType>;
return UnboundedVariant(mem_res, in_place_type_t{}, list, std::forward<Args>(args)...);
}

/// \brief Performs type-safe access to the contained object.
///
/// \param operand Target unbounded_variant object.
Expand Down

0 comments on commit 634fc25

Please sign in to comment.