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


On Fri, Mar 28, 2008 at 10:40 AM, Daniel Lidström <daniel.lidstrom@sbg.se> wrote:
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