Better way to write an object generator for an RAII template class?

Posted by Dan on Stack Overflow See other posts from Stack Overflow or by Dan
Published on 2010-04-29T18:45:22Z Indexed on 2010/04/29 18:47 UTC
Read the original article Hit count: 194

Filed under:
|
|

I would like to write an object generator for a templated RAII class -- basically a function template to construct an object using type deduction of parameters so the types don't have to be specified explicitly.

The problem I foresee is that the helper function that takes care of type deduction for me is going to return the object by value, which will result in a premature call to the RAII destructor when the copy is made. Perhaps C++0x move semantics could help but that's not an option for me.

Anyone seen this problem before and have a good solution?

This is what I have:

template<typename T, typename U, typename V>
class FooAdder
{
private:
  typedef OtherThing<T, U, V> Thing;
  Thing &thing_;
  int a_;
  // many other members
public:
  FooAdder(Thing &thing, int a);
  ~FooAdder();
  void foo(T t, U u);
  void bar(V v);
};

The gist is that OtherThing has a horrible interface, and FooAdder is supposed to make it easier to use. The intended use is roughly like this:

FooAdder(myThing, 2)
  .foo(3, 4)
  .foo(5, 6)
  .bar(7)
  .foo(8, 9);

The FooAdder constructor initializes some internal data structures. The foo and bar methods populate those data structures. The ~FooAdder dtor wraps things up and calls a method on thing_, taking care of all the nastiness.

That would work fine if FooAdder wasn't a template. But since it is, I would need to put the types in, more like this:

FooAdder<Abc, Def, Ghi>(myThing, 2) ...

That's annoying, because the types can be inferred based on myThing. So I would prefer to create a templated object generator, similar to std::make_pair, that will do the type deduction for me. Something like this:

template<typename T, typename U, typename V>
FooAdder<T, U, V>
AddFoo(Thing &thing, int a)
{
  return FooAdder<T, U, V>(thing, a);
}

That seems problematic: because it returns by value, the stack temporary object will be destructed, which will cause the RAII dtor to run prematurely.

One thought I had was to give FooAdder a copy ctor with move semantics, kinda like std::auto_ptr. But I would like to do this without dynamic memory allocation, so I thought the copy ctor could set a flag within FooAdder indicating the dtor shouldn't do the wrap-up. Like this:

FooAdder(FooAdder &rhs) // Note: rhs is not const
  : thing_(rhs.thing_)
  , a_(rhs.a_)
  , // etc... lots of other members, annoying.
  , moved(false)
{
  rhs.moved = true;
}

~FooAdder()
{
  if (!moved)
  {
    // do whatever it would have done
  }
}

Seems clunky. Anyone got a better way?

© Stack Overflow or respective owner

Related posts about c++

Related posts about templates