1

テンプレート化された関数の特性を使用して、明示的なコンストラクター/デストラクターを呼び出そうとしています。

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'

いくつかの括弧またはキーワードが欠落していると思われます。

アップデート

人々はなぜ私がこれを行っているのかと尋ねます... はい、予想通り、メモリプールを使用し、クライアントに 2 つの機能を提供したいと考えています。内部的には、malloc/free のメモリ プールへの静的ポインタを使用します。

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

もちろん、このアプローチには制限があります...デフォルトのコンストラクターしか使用できないなどです。new をオーバーロードすることも考えましたが、すべての type_t の new をオーバーロードする必要があり、既存のコードの動作が変更されます。

4

2 に答える 2

1

MSDN サイトには、次のが示されています。

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
于 2012-08-16T13:37:00.880 に答える
0

個人的には、ローカルの 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;
于 2012-08-16T13:39:09.533 に答える