Utility class that disallows dynamic creation
Hello!
I've created a class whose purpose is to disallow dynamic creation, sort of
like boost::noncopyable. I want to make sure that clients of my classes do
not use them in an unsafe way. So I disable operator new and address-of. We
have a lot of code here that doesn't use RAII, uses new/delete scattered
throughout, etc. This is an attempt at resolving these issues from this
point on.
Here's the implementation:
struct disallow_dynamic
{
private:
// disallow operator new
void* operator new(std::size_t);
void* operator new(std::size_t, const std::nothrow_t&) throw();
void* operator new[](std::size_t);
void* operator new[](std::size_t, const std::nothrow_t&) throw();
// disallow address-of
const disallow_dynamic* operator&() const;
/* */ disallow_dynamic* operator&() /* */;
};
This class should be used in the following way:
struct DataIO : private disallow_dynamic
{
....
};
Now you are only able to create DataIO instances on the stack. This is
great when combined with shared_ptr. For example, I have an interface
called IDataIO:
struct IDataIO
{
virtual void Write(const std::string& str) = 0;
virtual void Read(char* buffer, std::size_t size) = 0;
};
typedef boost::shared_ptr<IDataIO> IDataIOPtr;
Using this interface is a little bit awkward: typing IDataIOPtr is loong,
and I have to use ->. Just a little bit too pointer-like (new/delete is not
far away with pointers). Also, there is always the risk of someone misusing
shared_ptr by extracting the raw pointer. Let me show the nice solution:
// create a wrapper class that derives from IDataIO,
// and disallows dynamic usage
struct DataIO : IDataIO, private disallow_dynamic
{
DataIO(IDataIOPtr dataIO) : mDataIO(dataIO) {}
void Write(const std::string& str) { mDataIO->Write(str); }
void Read(char* buffer, std::size_t size){ mDataIO->Read(buffer, size);}
}
private:
IDataIOPtr mDataIO;
};
Now it's impossible to misuse the IDataIO hierarchy! Here's a typical usage
scenario:
DataIO dataIO = CreateDataIO(0);
dataIO.Write("Hej hopp");
char buffer[1024];
dataIO.Read(buffer, sizeof(buffer));
There is no way to obtain a pointer to IDataIO, or DataIO. No risks here!
What do you think? Is the disallow_dynamic class named properly,
implemented correctly, useful at all? Looking forward to any comments :-)
--
Daniel