manually calling a template argument constructor, How ???

N

Nadav

Hi,

I am trying to manually call a constructor of a template argument, the
compiler returns “error C2039: ‘T’ : is not a member...â€

How can I manually call the constructor of a template argument?

Please note that I cannot use the ‘new’ operator ( as long as it allocates
memory ), see the following code snnipet as an example of what I am trying to
do.


class HEADER {
LONG lStam;
HEADER() : lStam(0) {}
};

template< typename T >
class CMyTest
{
protected:
CMyTest();
~CMyTest();

typename T m_pObjects[0];
public:
static HRESULT CreateInstance(IN int iObjCount, OUT CMyTest** ppObj) {
*ppObj = (CMyTest*)malloc(sizeof(CMyTest) + sizeof(T) * iObjCount);
if(0 == *ppObj)
return E_OUTOFMEMORY;
(*ppObj)->CMyTest::CMyTest();// Works, calls the constructor
for(int i = 0; i < iObjCount; i++)
(*ppObj)->m_pObjects[0].T::T();// error C2039: 'T' : is not a member of
'HEADER'
}
};

int _tmain(int argc, _TCHAR* argv[])
{
CMyTest<HEADER>* pTest;
CMyTest<HEADER>::CreateInstance(10, &pTest);
}

The above code doesn’t have any practical meaning, it’s only goal is to
demonstrate the problem I am describing here
 
C

Carl Daniel [VC++ MVP]

Nadav said:
Hi,

I am trying to manually call a constructor of a template argument, the
compiler returns "error C2039: 'T' : is not a member..."

How can I manually call the constructor of a template argument?

Please note that I cannot use the 'new' operator ( as long as it
allocates memory ), see the following code snnipet as an example of
what I am trying to do.
(*ppObj)->CMyTest::CMyTest();// Works, calls the constructor

VC++ Extension, not portable C++ code. There's no way to "call a
constructor" in standard C++.
for(int i = 0; i < iObjCount; i++)
(*ppObj)->m_pObjects[0].T::T();// error C2039: 'T' : is not a
member of 'HEADER'

Here the extension fails.
The above code doesn't have any practical meaning, it's only goal is
to demonstrate the problem I am describing here

The correct way to do this is to use "placement new":

#include <new>

// (*ppObj)->CMyTest::CMyTest(); // Non-standard VC++ extension

new (*ppObj) CMyTest(); // standard, placement-new solution

// (*ppObj)->m_pObjects[0].T::T(); // extension breaks down

new (*ppObj) T(); // standard, placement-new solution

-cd
 
B

Ben Voigt [C++ MVP]

Carl Daniel said:
Nadav said:
Hi,

I am trying to manually call a constructor of a template argument, the
compiler returns "error C2039: 'T' : is not a member..."

How can I manually call the constructor of a template argument?

Please note that I cannot use the 'new' operator ( as long as it
allocates memory ), see the following code snnipet as an example of
what I am trying to do.
(*ppObj)->CMyTest::CMyTest();// Works, calls the constructor

VC++ Extension, not portable C++ code. There's no way to "call a
constructor" in standard C++.
for(int i = 0; i < iObjCount; i++)
(*ppObj)->m_pObjects[0].T::T();// error C2039: 'T' : is not a
member of 'HEADER'

Here the extension fails.

I think I once found that using a typedef solves the problem as well (and
solves the problem of how to invoke the destructor as well, so even if you
construct with placement new you may still need the trick.

typedef typename T TValue;
TValue* pT = (TValue*)malloc(sizeof(TValue));
pT->TValue(); or pT->TValue::TValue();
....
pT->~TValue(); or pT->TValue::~TValue();
The above code doesn't have any practical meaning, it's only goal is
to demonstrate the problem I am describing here

The correct way to do this is to use "placement new":

#include <new>

// (*ppObj)->CMyTest::CMyTest(); // Non-standard VC++ extension

new (*ppObj) CMyTest(); // standard, placement-new solution

// (*ppObj)->m_pObjects[0].T::T(); // extension breaks down

new (*ppObj) T(); // standard, placement-new solution

-cd
 
C

Carl Daniel [VC++ MVP]

Ben said:
I think I once found that using a typedef solves the problem as well
(and solves the problem of how to invoke the destructor as well, so
even if you construct with placement new you may still need the trick.

typedef typename T TValue;
TValue* pT = (TValue*)malloc(sizeof(TValue));
pT->TValue(); or pT->TValue::TValue();
...
pT->~TValue(); or pT->TValue::~TValue();

The difference is, for the destructor

template<class T> ...
T* pt = ...
pt->~T();

is required to work by the C++ standard (at least, I'm pretty sure it's
required to work!), and does work under VC++ 2005 (I didn't try anything
older). The typedef trick may be required for some older versions - I don't
have anything older installed to try it out.

-cd
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top