Consider a class with a member that can't be stored directly, e.g., because it does not have a default constructor, and the enclosing class's constructor doesn't have enough information to create it:
class Foo
{
public:
Foo(){} // Default ctor
private:
/* Won't build: no default ctor or way to call it's
non-default ctor at Foo's ctor. */
Bar m_bar;
};
Clearly, m_bar
needs to be stored differently, e.g., through a pointer. A std::unique_ptr
seems better, though, as it will destruct it automatically:
std::unique_ptr<Bar> m_bar;
It's also possible to use std::experimental::optional
, though:
std::experimenatl::optional<Bar> m_bar;
My questions are: 1. What are the tradeoffs? and 2. Does it make sense to build a class automating the choice between them?
Specifically, looking at the exception guarantees for the ctor of std::unique_ptr
and the exception guarantees for the ctor of std::experimental::optional
, it seems clear that the former must perform dynamic allocation and deallocation - runtime speed disadvantages, and the latter stores things in some (aligned) memory buffer - size disadvantages. Are these the only tradeoffs?
If these are indeed the tradeoffs, and given that both types share enough of their interface (ctor, operator*
), does it make sense to automate the choice between them with something like
template<typename T>
using indirect_raii = typename std::conditional<
// 20 - arbitrary constant
sizeof(std::experimental::optional<T>) >
20 + sizeof(std::exerimental::optional<T>)sizeof(std::unique_ptr<T>),
std::unique_ptr<T>,
std::experimental::optional<T>>::type;
(Note: there is a question discussing the tradeoffs between these two as return types, but the question and answers focus on what each conveys to the callers of the function, which is irrelevant for these private members.)