Declaring class template constructor and destructor outside of the class ?

S

Skybuck Flying

Question:

How to declare class template constructor and destructor outside the class ?

(I cannot find a good example on the internet or in the books (from years
ago) or in the help files).

How to modify this basic example so the link errors are gone ?

// TestProgram.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

template <class GenericType>
class Ttest
{
private:
GenericType mField1;
GenericType mField2;

public:

Ttest();
~Ttest();

};

Ttest::Ttest()
{


}

Ttest::~Ttest()
{

}


int _tmain(int argc, _TCHAR* argv[])
{
Ttest<int> a;
Ttest<int> b;

// getting link errors.

return 0;
}

Bye,
Skybuck.

P.S.: Most examples declare them inside the class declaration which is quite
bad programming style, it clutters it badly, this should have never been
allowed in c++, but that's my personal oppinion ;) fortunately Delphi does
not have it, keep it consistent I say... all inside or all outside, not half
half.
 
S

Skybuck Flying

Ok I figured it out based on this cryptic example:

http://msdn.microsoft.com/en-us/library/x5w1yety(v=vs.71).aspx

Apperently the trick is to add

template <class GenericType>

before each function/routine in the implementation section.


// TestProgram.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

template <class GenericType>
class Ttest
{
private:
// GenericType *mField1;
// GenericType *mField2;
public:

Ttest();
~Ttest();

};

template <class GenericType>
Ttest<GenericType>::Ttest()
{


}

template <class GenericType>
Ttest<GenericType>::~Ttest()
{

}


int _tmain(int argc, _TCHAR* argv[])
{
Ttest<int> a;
Ttest<int> b;

return 0;
}

Bye,
Skybuck.
 
G

Gert-Jan de Vos

Question:

How to declare class template constructor and destructor outside the class ?

(I cannot find a good example on the internet or in the books (from years
ago) or in the help files).

How to modify this basic example so the link errors are gone ?

// TestProgram.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

template <class GenericType>
class Ttest
{
private:
  GenericType mField1;
  GenericType mField2;

public:

  Ttest();
  ~Ttest();

};

Ttest::Ttest()
{

}

Ttest::~Ttest()
{

}

It's only inside the class template definition that the template name
may be used as the class name. Outside the definition, the template
name needs the template argument list to become a class name. So your
constructor and destructor definitions are now similar to function
templates:

template <class GenericType>
Ttest<GenericType>::Ttest()
{
}

template <class GenericType>
Ttest<GenericType>::~Ttest()
{
}
 
F

Fedor Rodikov

It's only inside the class template definition that the template name
may be used as the class name. Outside the definition, the template
name needs the template argument list to become a class name. So your
constructor and destructor definitions are now similar to function
templates:

template <class GenericType>
Ttest<GenericType>::Ttest()
{

}

template <class GenericType>
Ttest<GenericType>::~Ttest()
{







}

Don't forget to define constructors and destructors as inline to avoid
multiple definitions in different translation units.

template <class GenericType>
inline Ttest<GenericType>::Ttest()
{
}

template <class GenericType>
inline Ttest<GenericType>::~Ttest()
{
}
 
G

Gert-Jan de Vos

Don't forget to define constructors and destructors as inline to avoid
multiple definitions in different translation units.

template <class GenericType>
inline Ttest<GenericType>::Ttest()
{
}

template <class GenericType>
inline Ttest<GenericType>::~Ttest()
{
}

Of course, thank you. This is why I usually prefer to just implement
class templates inline. I do try hard to keep template classes short
with a single responsibility only. Then document the interface and
its typical use separately. I think its more important to separate
hierarchical concepts into individual classes than it is to separate
interface from implementation. While a valuable thing, template
technicalities make this separation cumbersome for template classes.
 
F

Fedor Rodikov

Of course, thank you. This is why I usually prefer to just implement
class templates inline. I do try hard to keep template classes short
with a single responsibility only. Then document the interface and
its typical use separately. I think its more important to separate
hierarchical concepts into individual classes than it is to separate
interface from implementation. While a valuable thing, template
technicalities make this separation cumbersome for template classes.

I agree with you.

Though I want to point out that there is cases when this seperation
impossible.
For example, yesterday I tried (without success) to seperate interface
and implementation for
template specializations that use boost::enable_if. Code was like
this:

template< typename A, typename B, typename D = void >
struct C;

template< typename A, typename B >
struct C< A, B, typename boost::enable_if_c< A::value == 1 >::type >
{
void f()
{
}
};

May be you know how to solve this problem?
 
J

Juha Nieminen

In comp.lang.c++ Fedor Rodikov said:
Don't forget to define constructors and destructors as inline to avoid
multiple definitions in different translation units.

You don't have to do that with templates. They are implicity inline.
 
A

Alf P. Steinbach /Usenet

* Juha Nieminen, on 05.07.2011 07:52:
You don't have to do that with templates. They are implicity inline.

Nit-picking, it's not quite the same. The keyword "inline" (or having that
implicitly implied) adds a hinting effect about optimization. But I don't know
good terminology -- when this has been discussed earlier, people have pointed
out that terminology that refers to the now common primitive linking technology
would be meaningless for the early C++ compilers' treatment of templates.


Cheers,

- Alf
 
F

Fedor Rodikov

* Juha Nieminen, on 05.07.2011 07:52:



Nit-picking, it's not quite the same. The keyword "inline" (or having that
implicitly implied) adds a hinting effect about optimization. But I don'tknow
good terminology -- when this has been discussed earlier, people have pointed
out that terminology that refers to the now common primitive linking technology
would be meaningless for the early C++ compilers' treatment of templates.

Cheers,

- Alf

Thank you for last two remarks.

In fact, it was my mistake.
According to the C++ standard, member function templates do not
violate ODR if
there is at least one unspecified template parameter. For example for
full
template specializations my VC++2008 issues linker errors.


template< typename T >
struct X;

template<> struct X< int >
{
X();
~X();
};

X< int >::X() {}
X< int >::~X() {}

1>b.obj : error LNK2005: "public: __thiscall X<int>::X<int>(void)" (??
0?$X@H@@QAE@XZ) already defined in a.obj
1>b.obj : error LNK2005: "public: __thiscall X<int>::~X<int>(void)" (??
1?$X@H@@QAE@XZ) already defined in a.obj
 
J

Juha Nieminen

In comp.lang.c++ Alf P. Steinbach /Usenet said:
* Juha Nieminen, on 05.07.2011 07:52:

Nit-picking, it's not quite the same. The keyword "inline" (or having that
implicitly implied) adds a hinting effect about optimization.

Do modern compilers really take the keyword into account at all when
deciding whether to inline a function or not? My understanding is (although
I can't give any references) that compilers treat the 'inline' keyword as
a no-op when making optimization decisions (and basically treat it purely
as an instruction for the linker). After all, compilers are free to inline
functions or not inline them as they wish, as long as the behavior of the
program doesn't change.
 
A

Alf P. Steinbach /Usenet

* Juha Nieminen, on 05.07.2011 18:00:
Do modern compilers really take the keyword into account at all when
deciding whether to inline a function or not?

g++ does more, msvc does less.

don't know about others.

My understanding is (although
I can't give any references) that compilers treat the 'inline' keyword as
a no-op when making optimization decisions (and basically treat it purely
as an instruction for the linker). After all, compilers are free to inline
functions or not inline them as they wish, as long as the behavior of the
program doesn't change.

as with all hinting, they can ignore it, and if they're going to do a good job
they'd better ignore it (since compiler generally knows more than programmer does)


cheers,

- alf
 

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

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top