tags:

views:

174

answers:

3

Maybe I'm overcomplicating things, but then again, I do sort of like clean interfaces. Let's say I want a specialization of auto_ptr for an fstream - I want a default fstream for the generic case, but allow a replacement pointer?

 template <> 
 class auto_ptr<fstream> {
     static fstream myfStream; 
     fstream* ptr; 

 public: 
     auto_ptr() { 
         // set ptr to &myfStream;
     }
     reset(fstream* newPtr) {
         // free old ptr if not the static one. 
         ptr = newPtr 
     };
  } 

Would you consider something different or more elegant? And how would you keep something like the above from propagating outside this particular compilation unit?

[The actual template is a boost::scoped_ptr.]

EDIT:

It's a contrived example. Ignore the fstream - it's about providing a default instance of object for an auto_ptr. I may not want to provide a specialized instance, but would like to keep the auto_ptr semantics for this static default object.

class UserClass { 
public:
    auto_ptr<fstream> ptr; 
    UserClass() {  }
} 

I may not provide an dynamic object at construction time - I still want it to have a meaningful default. Since I'm not looking at ownership-transfer semantics, it really shouldn't matter that my pointer class is pointing to a statically allocated object, no?

+1  A: 

That looks reasonable to me, could be confusing if it's use is widespread in a codebase and not documented though.

I notice you are being carful, but I'm going to stress it anyway: make sure you don't double-free your static object!

Autopulated
The alternative is creating an auto_ptr and assigning a default value and then reset()ing it's value later, or do it in the constructor. I know where I'd rather have it be done.
Chris Kaminski
+2  A: 

This wouldn't end up good. The biggest problem is that std::auto_ptr deletes the underlying object in its destructor. This means your default parameter can't be static. The only choice you can make is to do a lot of hacks there and IMHO the price you'll pay while maintaining all that crappy code isn't worth the small advantage you'd have.

buratinas
I'd probably typedef it, and auto_ptr was a based choice, boost::scoped_ptr would probably be a better basis.
Chris Kaminski
+1  A: 

You might get something that compiles and works, but I wouldn't do that if I were you.

Boost defines certain functionality for the construction of an auto_ptr. If you redefine that somehow, you have violated their specification.

Invent a name for your new functionality, make it a factory function, and don't worry about specializing someone else's template.

EDIT: deriving from auto_ptr is another option, if you're really set on changing initialization semantics:

tempate < class T, T *d > 
struct defaulted_auto_ptr
    : public auto_ptr< T > {
    defaulted_auto_ptr( T *p = d ) throw() : auto_ptr<T>( p ) {} // set default
    defaulted_auto_ptr( auto_ptr<T> &r ) throw()
        : auto_ptr<T>( r ) {} // allow conversion
    template< class O > defaulted_auto_ptr( auto_ptr<O> &r ) throw()
        : auto_ptr<T>( r ) {}
};

fstream default_file;
typedef defaulted_auto_ptr< fstream, &default_file > file_ptr;

auto_ptr< fstream > baseptr = file_ptr(); // can assign to auto_ptr, but unsafe

I'm a little doubtful of the cost-benefit tradeoff of this, but it's better than entirely reimplementing auto_ptr.

You still have to figure out what to do if a defaulted object is destroyed. default_file above will be deleted, potentially many times.

Potatoswatter
Except it's not really a factory. The idiom is that I have a pointer, and it want it to have a known default value. It can be changed at any time. I suppose I can take care to simply assign a default value, but it's something I'd rather have done in a constructor.
Chris Kaminski