1

I'm trying to call explicit constructor/destructor with traits in templatized function.

template <int i>
struct Traits
{
};
template <>
struct Traits<1>
{
  typedef Foo type_t;
};
template <>
struct Traits<2>
{
  typedef Bar type_t;
};

template <class Traits>
void DoSomething(void* p_in)
{
  typename Traits::type_t* p = reinterpret_cast<typename Traits::type_t*>(p_in);
  // this works.
  new (p) typename Traits::type_t;
  // neither of following two does work.
  p->~typename Traits::type_t();
  p->typename ~Traits::type_t();
}

// call
void* p_in = malloc(BIG_ENOUGH);
DoSomething<Traits<1> >(p_in);
free(p_in);

In GCC 4.4.3 with -ansi flag, calling explicit constructor works fine. However, calling explicit destructor does not work, giving following error:

error: expected identifier before 'typename'
error: expected ';' before 'typename'

I suspect some parentheses or keyword is missing.

UPDATE

People ask about why I am doing this... Yes, as expected, I want to use memory pool, and give two functions to clients. Internally it uses a static pointer to the memory pool for malloc/free.

template<class Traits>
typename Traits::type_t* memory_pool_new();
template<class Traits>
void memory_pool_delete();

Of course this approach has limitations... like only default constructor can be used. I thought about overloading new, but it requires overloading new of all type_t's, and it will change the behavior of existing codes.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
xosp7tom
  • 2,131
  • 1
  • 17
  • 26

2 Answers2

1

The MSDN site gives this example:

To explicitly call the destructor for an object, s, of class String, use one of the following statements:

s.String::~String();     // Nonvirtual call
ps->String::~String();   // Nonvirtual call

s.~String();       // Virtual call
ps->~String();     // Virtual call

So you could try to add a typedef and mimic the above with:

typedef typename Traits::type_t TraitsType;

// we now have that p is of TraitsType*
p->TraitsType::~TraitsType(); // nonvirtual call
p->~TraitsType();             // virtual call
TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • Thanks- It works like a charm! I read MSDN, but couldn't think of adding typedef. – xosp7tom Aug 16 '12 at 13:39
  • If he's using some kind of memory pool and uses in-place construction, explicitly calling the destructor might be useful. – Cubic Aug 16 '12 at 13:44
  • @Cubic I see now, but much better to overload class-specific `operator new` then to not confuse clients. `DoSomething` suggests a regular function at work, not some fancy memory allocation. – TemplateRex Aug 16 '12 at 13:46
  • Using a typedef inside my template function worked nicely for me to delete the inplace constructed object using the typedef name. Thanks! – Glenn Feb 04 '17 at 07:53
0

Personally, I'd use a local typedef since typename Traits::type_t is a bit of a mouthful. If you don't want to do that, then the destructor syntax is:

p->Traits::type_t::~type_t();

By the way, there's no need to mess around with reinterpret_cast; you can simply initialise the typed pointer from the new expression:

typename Traits::type_t* p = new (p_in) typename Traits::type_t;
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644