From 634fc25d26e44a32048a3bba98306be7d77b1d5b Mon Sep 17 00:00:00 2001 From: Sergei Shirokov Date: Wed, 5 Jun 2024 10:18:37 +0300 Subject: [PATCH] More `make_unbounded_variant` --- .../unittest/test_unbounded_variant.cpp | 48 +++++++ include/cetl/unbounded_variant.hpp | 122 ++++++++++++++---- 2 files changed, 147 insertions(+), 23 deletions(-) diff --git a/cetlvast/suites/unittest/test_unbounded_variant.cpp b/cetlvast/suites/unittest/test_unbounded_variant.cpp index 640cfa9..608571d 100644 --- a/cetlvast/suites/unittest/test_unbounded_variant.cpp +++ b/cetlvast/suites/unittest/test_unbounded_variant.cpp @@ -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(get_mr(), "Hello, cetl::unbounded_variant!\n"); + auto a1 = make_unbounded_variant, ub_var>(get_mr(), 0.1, 2.3); + + EXPECT_THAT(get(a0), "Hello, cetl::unbounded_variant!\n"); + EXPECT_THAT(get>(a1), std::complex(0.1, 2.3)); + + using lambda = std::function; + using ub_var_lambda = cetl::unbounded_variant<0, true, true, alignof(std::max_align_t), pmr>; + + auto a3 = make_unbounded_variant(get_mr(), [] { return "Lambda #3.\n"; }); + EXPECT_TRUE(a3.has_value()); + EXPECT_THAT(get(a3)(), "Lambda #3.\n"); +} + +TEST_F(TestPmrUnboundedVariant, pmr_make_unbounded_variant_1) +{ + using ub_var = unbounded_variant; + + auto src = make_unbounded_variant(get_mr(), 42); + EXPECT_THAT(get(src), 42); + static_assert(std::is_same::value, ""); +} + +TEST_F(TestPmrUnboundedVariant, pmr_make_unbounded_variant_2_list) +{ + struct MyType : rtti_helper> + { + std::size_t size_; + int number_; + + MyType(const std::initializer_list chars, const int number) + { + size_ = chars.size(); + number_ = number; + } + }; + using ub_var = unbounded_variant; + + const auto src = make_unbounded_variant(get_mr(), {'A', 'C'}, 42); + const auto& test = get(src); + EXPECT_THAT(test.size_, 2); + EXPECT_THAT(test.number_, 42); +} + } // namespace namespace cetl diff --git a/include/cetl/unbounded_variant.hpp b/include/cetl/unbounded_variant.hpp index af94954..5e66dde 100644 --- a/include/cetl/unbounded_variant.hpp +++ b/include/cetl/unbounded_variant.hpp @@ -994,13 +994,21 @@ class unbounded_variant : detail::base_move; + 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 @@ -1014,8 +1022,6 @@ class unbounded_variant : detail::base_move> unbounded_variant() { @@ -1047,12 +1053,9 @@ class unbounded_variant : detail::base_move(std::forward(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. @@ -1136,11 +1140,10 @@ class unbounded_variant : detail::base_move(list, std::forward(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. @@ -1472,29 +1475,102 @@ using unbounded_variant_like = unbounded_variant::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... Args> +template , + typename... Args, + typename = std::enable_if_t> CETL_NODISCARD UnboundedVariant make_unbounded_variant(Args&&... args) { using in_place_type_t = typename UnboundedVariant::template in_place_type_t; return UnboundedVariant(in_place_type_t{}, std::forward(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 Up, - typename... Args> + typename... Args, + typename = std::enable_if_t> CETL_NODISCARD UnboundedVariant make_unbounded_variant(std::initializer_list list, Args&&... args) { using in_place_type_t = typename UnboundedVariant::template in_place_type_t; return UnboundedVariant(in_place_type_t{}, list, std::forward(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... Args, + typename Pmr = typename UnboundedVariant::PmrType, + typename = std::enable_if_t> +CETL_NODISCARD UnboundedVariant make_unbounded_variant(Pmr* const mem_res, Args&&... args) +{ + using in_place_type_t = typename UnboundedVariant::template in_place_type_t; + return UnboundedVariant(mem_res, in_place_type_t{}, std::forward(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 Up, + typename... Args, + typename Pmr = typename UnboundedVariant::PmrType, + typename = std::enable_if_t> +CETL_NODISCARD UnboundedVariant make_unbounded_variant(Pmr* const mem_res, + std::initializer_list list, + Args&&... args) +{ + using in_place_type_t = typename UnboundedVariant::template in_place_type_t; + return UnboundedVariant(mem_res, in_place_type_t{}, list, std::forward(args)...); +} + /// \brief Performs type-safe access to the contained object. /// /// \param operand Target unbounded_variant object.