variant: add mutable unwrap and visitation
This commit is contained in:
parent
bc3cec4634
commit
2a7435e026
@ -62,7 +62,6 @@ namespace tools
|
||||
|
||||
////
|
||||
// variant: convenience wrapper around boost::variant with a cleaner interface
|
||||
// - the value may be assigned to but is otherwise read-only
|
||||
// - the variant is 'optional' - an empty variant will evaluate to 'false' and an initialized variant will be 'true'
|
||||
///
|
||||
template <typename ResultT>
|
||||
@ -70,6 +69,7 @@ struct variant_static_visitor : public boost::static_visitor<ResultT>
|
||||
{
|
||||
/// provide visitation for empty variants
|
||||
/// - add this to your visitor with: using variant_static_visitor::operator();
|
||||
[[noreturn]] ResultT operator()(const boost::blank) { variant_static_visitor_blank_err(); }
|
||||
[[noreturn]] ResultT operator()(const boost::blank) const { variant_static_visitor_blank_err(); }
|
||||
};
|
||||
|
||||
@ -107,14 +107,20 @@ public:
|
||||
template <typename T>
|
||||
bool is_type() const noexcept { return this->index() == this->type_index_of<T>(); }
|
||||
|
||||
/// try to get a read-only handle to the embedded value (return nullptr on failure)
|
||||
/// try to get a handle to the embedded value (return nullptr on failure)
|
||||
template <typename T>
|
||||
const T* try_unwrap() const
|
||||
{
|
||||
return boost::strict_get<T>(&m_value);
|
||||
}
|
||||
T* try_unwrap() noexcept { return boost::strict_get< T>(&m_value); }
|
||||
template <typename T>
|
||||
const T* try_unwrap() const noexcept { return boost::strict_get<const T>(&m_value); }
|
||||
|
||||
/// get a read-only handle to the embedded value
|
||||
/// get a handle to the embedded value
|
||||
template <typename T>
|
||||
T& unwrap()
|
||||
{
|
||||
T *value_ptr{this->try_unwrap<T>()};
|
||||
if (!value_ptr) variant_unwrap_err();
|
||||
return *value_ptr;
|
||||
}
|
||||
template <typename T>
|
||||
const T& unwrap() const
|
||||
{
|
||||
@ -131,7 +137,7 @@ public:
|
||||
static constexpr int type_index_of() noexcept
|
||||
{
|
||||
using types = boost::mpl::vector<boost::blank, Types...>;
|
||||
using elem = typename boost::mpl::find<types, T>::type;
|
||||
using elem = typename boost::mpl::find<types, T>::type;
|
||||
using begin = typename boost::mpl::begin<types>::type;
|
||||
return boost::mpl::distance<begin, elem>::value;
|
||||
}
|
||||
@ -142,6 +148,11 @@ public:
|
||||
|
||||
/// apply a visitor to the variant
|
||||
template <typename VisitorT>
|
||||
typename VisitorT::result_type visit(VisitorT &&visitor)
|
||||
{
|
||||
return boost::apply_visitor(std::forward<VisitorT>(visitor), m_value);
|
||||
}
|
||||
template <typename VisitorT>
|
||||
typename VisitorT::result_type visit(VisitorT &&visitor) const
|
||||
{
|
||||
return boost::apply_visitor(std::forward<VisitorT>(visitor), m_value);
|
||||
|
@ -232,8 +232,10 @@ struct test_stringify_visitor: public variant_static_visitor<std::string>
|
||||
return test_stringify_visitor::stringify(t);
|
||||
}
|
||||
};
|
||||
} // anonymous namespace
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
} // anonymous namespace
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
TEST(variant, operatorbool)
|
||||
{
|
||||
@ -295,6 +297,25 @@ TEST(variant, unwrap)
|
||||
EXPECT_THROW(v.unwrap<std::string>(), std::runtime_error);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
TEST(variant, mutation)
|
||||
{
|
||||
variant<uint8_t> v;
|
||||
v = (uint8_t) 5;
|
||||
EXPECT_EQ(5, v.unwrap<uint8_t>());
|
||||
uint8_t &intref{v.unwrap<uint8_t>()};
|
||||
intref = 10;
|
||||
EXPECT_EQ(10, v.unwrap<uint8_t>());
|
||||
EXPECT_TRUE(v.try_unwrap<uint8_t>());
|
||||
uint8_t *intptr{v.try_unwrap<uint8_t>()};
|
||||
*intptr = 15;
|
||||
EXPECT_EQ(15, v.unwrap<uint8_t>());
|
||||
|
||||
const variant<uint8_t> &v_ref{v};
|
||||
EXPECT_EQ(15, v_ref.unwrap<uint8_t>());
|
||||
EXPECT_TRUE(v_ref.try_unwrap<uint8_t>());
|
||||
EXPECT_EQ(15, *(v_ref.try_unwrap<uint8_t>()));
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
TEST(variant, index)
|
||||
{
|
||||
variant<int8_t, uint8_t, int16_t, uint16_t, std::string> v;
|
||||
|
Loading…
Reference in New Issue
Block a user