Consider a MemoryMappedFile
class, with the following data members:
class MemoryMappedFile
{
....
private:
// RAII wrapper to some OS-specific raw handle (e.g. Win32 HANDLE),
// representing the memory-mapped file.
Handle m_handle;
// Pointer to file begin (first file byte).
BYTE* m_first;
// Pointer to file end (one byte past last file byte).
BYTE* m_last;
};
The Handle
class is some RAII wrapper to some specific OS raw C-like handle (e.g. think of Win32 HANDLE
). It is not copyable, but it is movable.
Instead, m_first
and m_last
are raw pointers inside the memory area mapped with the file content.
I'd like the MemoryMappedFile
class to be movable (but not copyable, just like the Handle
class).
If it weren't for the raw pointers, according to C++11's rules of automatic generation of move constructor by member-wise moves, the class would be automatically movable.
Unfortunately, the raw pointers force me to write a custom move constructor:
MemoryMappedFile::MemoryMappedFile(MemoryMappedFile&& other)
: m_handle( std::move(other.m_handle) )
{
// Move m_first
m_first = other.m_first;
other.m_first = nullptr;
// Move m_last
m_last = other.m_last;
other.m_last = nullptr;
}
It would be nice if C++ standard library had some form of "dumb-as-opposed-to-smart but movable" pointer, with zero-overhead, just like raw pointers (which are fine as observing non-owning pointers), but with move operations (move constructor and move assignment) defined, such that the compiler can automatically generate correct move operations in classes that have these pointers as data members.
Is there something like this in C++ standard library, or in Boost?
Or is there any other way to achieve the same goal (beside writing my own custom ObservingPointer class, wrapping raw pointers and defining move operations)?
Just use a
std::unique_ptr
with your ownnoop_deleter
.I frequently need a "smart" pointer that is both copyable and movable, but has a well-defined moved-from state, so I wrote
tidy_ptr
which is a "dumb" smart pointer that does nothing special except zero itself on move. That type is copyable, so to get the semantics you want for your class you would still need to define the copy operations as deleted (or just usestd::unique_ptr
with a no-op deleter).I've tried to convince the standards committee that
observer_ptr
, "the world's dumbest smart pointer", should have this behaviour, but the consensus was that it should behave just like a built-in pointer (except for zero-initialization in the constructor). I still think it should zero on move. That paper shows anon_owning_ptr
which is an alias forunique_ptr
with a no-op deleter, which does what you want.