【问题标题】:Call explicit constructor/destructor with traits in templatized function在模板化函数中调用具有特征的显式构造函数/析构函数
【发布时间】:2012-08-12 20:44:34
【问题描述】:

我正在尝试使用模板化函数中的特征调用显式构造函数/析构函数。

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);

在带有 -ansi 标志的 GCC 4.4.3 中,调用显式构造函数可以正常工作。但是,调用显式析构函数不起作用,出现以下错误:

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

我怀疑缺少一些括号或关键字。

更新

人们问我为什么要这样做......是的,正如预期的那样,我想使用内存池,并为客户端提供两个功能。在内部,它使用一个静态指针指向 malloc/free 的内存池。

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

当然,这种方法有局限性……比如只能使用默认构造函数。我想过重载new,但它需要重载所有type_t的new,它会改变现有代码的行为。

【问题讨论】:

  • 你为什么要调用析构函数??
  • 实际上你想做什么?试图调用哪个析构函数?

标签: c++ typedef destructor traits delete-operator


【解决方案1】:

MSDN 网站给出了这个example

显式调用类的对象 s 的析构函数 String,使用以下语句之一:

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

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

所以你可以尝试添加一个 typedef 并模仿上面的:

typedef typename Traits::type_t TraitsType;

// we now have that p is of TraitsType*
p->TraitsType::~TraitsType(); // nonvirtual call
p->~TraitsType();             // virtual call

【讨论】:

  • 谢谢 - 它就像一个魅力!我读了 MSDN,但想不到添加 typedef。
  • 如果他正在使用某种内存池并使用就地构造,那么显式调用析构函数可能会有用。
  • @Cubic 我现在看到了,但是最好重载特定于类的operator new,然后不要混淆客户。 DoSomething 建议使用常规函数,而不是一些花哨的内存分配。
  • 在我的模板函数中使用 typedef 非常适合我使用 typedef 名称删除就地构造的对象。谢谢!
【解决方案2】:

就我个人而言,我会使用本地 typedef,因为 typename Traits::type_t 有点拗口。如果你不想这样做,那么析构函数的语法是:

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

顺便说一句,reinterpret_cast 没必要乱来;您可以简单地从新表达式初始化类型化指针:

typename Traits::type_t* p = new (p_in) typename Traits::type_t;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-14
    • 1970-01-01
    • 1970-01-01
    • 2016-06-07
    • 1970-01-01
    相关资源
    最近更新 更多