tags:

views:

53

answers:

2

Given a template class as such:

template <typename TYPE>
class SomeClass {
 public:
  typedef boost::intrusive_ptr<SomeClass<TYPE> > Client_t;
  inline Client_t GetClient() { return Client_t(this); }
};

SomeClass is intended only to be used via pointer references returned by SomeClass::GetClient(). Which makes it natural to write a wrapper function around creation like this:

template <typename TYPE>
SomeClass<TYPE>::Client_t New_SomeClass() { 
  return (new SomeClass<TYPE>)->GetClient(); 
}

Compiling the above code under GCC 4.4:

SomeClass<int>::Client_t some_class = New_SomeClass();

Gives the error "‘New_SomeClass’ was not declared in this scope"

Now I'm no template wizard, so there could be details here I'm not aware of, but I'm guessing I can't use a construct of this sort at all due to the fact that C++ doesn't allow overloading on return type.

I guess a...shiver... macro would solve it:

#define NEW_SOMECLASS(TYPE) ((new SomeClass<TYPE>)->GetClient())

auto some_class = NEW_SOMECLASS(int);

But there has to be a sensible way to expose object creation of a template class without resorting to macros or other cumbersome constructs?

A: 

you can try to use default type for template type parameter

Function templates cannot have defaults, and I'm not sure how it would help here as it appears 'int' is just part of the example.
Roger Pate
+1  A: 
SomeClass<int>::Client_t some_class = New_SomeClass<int>();

Because template parameters for New_SomeClass don't depend on a function parameter, you must specify them. The error message you reported is a little strange for this problem, however, so you might have something else going on.

Or, my preference instead of New_SomeClass function:

template<class T>
struct SomeClass {
  typedef boost::intrusive_ptr<SomeClass> Client;
  inline Client client() { return Client_t(this); }

  static Client create() { return (new SomeClass())->client(); }

private:
  SomeClass(); // can be public too, if you really need it accessible
};

//...
SomeClass<int>::Client some_class = SomeClass<int>::create();

Even though it essentially just moves the function "into" the class, I find it generally cleaner.

In any case, if your compiler supports 0x's 'auto' then you can use it:

auto some_class = SomeClass<int>::create();
Roger Pate
Two words: Excellent answer.