Hello Daniel,
I thought about such a class as well. The main disadvantage of it is that it is impossible to use with standard containers. :(
Standard containers (e.g. std::vector) pre-allocate space for some number of instances and use the placement new operator to place items in the pre-allocated memory and when deriving form
nondynamic makes it impossible.
With kind regards,
Ovanes
Hi there!
(I recently posted a similar message to microsoft.public.vc.language,
but the response was so bad I thought I would post here instead.)
I have created a utility class that I think is useful, called nondynamic.
The purpose is sort of like boost::noncopyable, but I disallow any dynamic/
pointer usages. For example, & and -> are disabled. Operator new/delete as
well.
Let me show nondynamic:
// all members are private
class nondynamic
{
// disallow operator new
static void* operator new(std::size_t);
static void* operator new(std::size_t, const std::nothrow_t&) throw();
static void* operator new[](std::size_t);
static void* operator new[](std::size_t, const std::nothrow_t&) throw();
// disallow operator delete
static void operator delete(void*){}
static void operator delete(void*, const std::nothrow_t&) throw(){}
static void operator delete[](void*){}
static void operator delete[](void*, const std::nothrow_t&) throw(){}
// disallow address-of
const nondynamic* operator&() const;
/* */ nondynamic* operator&() /* */;
// disallow ->
const nondynamic* operator->() const;
/* */ nondynamic* operator->() /* */;
};
Using this class is as simple as using boost::noncopyable:
struct DataIO : private nondynamic
{ ... };
Now you are only able to use DataIO as a value type. All other usages are
disabled. I think this promotes safe programming, in that pointer usage
is minimized (it seems with pointers, new/delete/null is never far away).
Let me illustrate how this class can be used most effectively. I thought
it would be nice to use nondynamic when you have a class hierarchy, and
a factory method.
Here's the base class:
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;
A sample subclass:
struct SerialDataIO : IDataIO
{
void Write(const std::string&) { std::cout << __FUNCTION__ << std::endl;
}
void Read(char*, std::size_t) { std::cout << __FUNCTION__ << std::endl; }
};
Here's the wrapper class that inherits from nondynamic:
struct DataIO : IDataIO, private nondynamic
{
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;
};
And finally, the factory:
DataIO CreateDataIO(int i)
{
if( i==0 )
return IDataIOPtr(new SerialDataIO);
else
throw std::runtime_error("Could not create DataIO");
}
Now the clients of the class hierarchy uses the wrapper, and are completely
isolated from pointers:
DataIO dataIO = CreateDataIO(0);
dataIO.Write("Hello");
char buffer[1024];
dataIO.Read(buffer, sizeof(buffer));
It should be impossible to misuse DataIO.
What do you think about nondynamic? Is it implemented correctly?
Named appropriately? Useful at all? Any comments gladly accepted :-)
Thanks in advance!
--
Daniel
_______________________________________________
Boost-users mailing list
Boost-users@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users