I’m writing a pointer wrapper class and want to replicate the following (great) functionality that std::unique_ptr
offers of allowing us to create a complete type from an incomplete one (in any scenario where we don’t need to call the destructor without knowing the type’s implementation, of course).
#include <memory>
struct Node
{
std::unique_ptr<Node> next_node;
};
I hypothesize that there is some requirement for a template for this to be possible. For example: the following happily compiles:
template<typename T>
struct PointerWrapper
{
T* member;
};
struct Node
{
PointerWrapper<Node> next;
};
And this (also happily) does not:
template<typename T>
struct dependent_type
{
T member;
};
struct Node
{
dependent_type<Node> next;
};
What are these requirements and how can I write my own class that satisfies them? For reference, designing a flagged reference class that looks as follows:
template<typename T>
struct FlaggedRef
{
static_assert(std::alignment_of_v<T> != 1, "need to steal the lowest bit");
FlaggedRef(T* ref = nullptr, bool flag = false) :
obj_ptr(reinterpret_cast<uintptr_t>(ref) | flag)
{}
bool get_flag()
{
return mask & obj_ptr;
}
void set_flag(bool flag)
{
obj_ptr = flag ? (obj_ptr | mask) : (obj_ptr & ~mask);
}
T* get_ptr()
{
return reinterpret_cast<T*>(obj_ptr & ~mask);
}
void set_ptr(T* ptr)
{
obj_ptr = reinterpret_cast<uintptr_t>(ptr) | get_flag();
}
private:
static constexpr uintptr_t mask = 1;
uintptr_t obj_ptr;
};
Which does not successfully hide the unknowness of a type, and so the same Node
example does not compile.