# Sind Template Methoden auch automatisch inline ?



## zarilla (21. Januar 2004)

Irgendwo hab ich mal gelesen das Methoden die direkt in der Klassendefinition definiert werden automatisch inline sind. 
Trifft das bei Templates auch zu ?


----------



## Thomas Kuse (21. Januar 2004)

Im Fall vom Visual C++ Compiler bin ich mir so ziemlich sicher, dass das auch bei Templates so ist.
Ein übersichtliches Programmieren erfordert an Sich schon ein separates Header-File, dann kann man die Methoden inline machen, die dafür geschaffen sind.
Die Sache ist aber, dass sowas wirklich vom Compiler und auch von gesetzten Compiler-Flags, wie man es beim gcc bzw g++ macht, abhängt


----------



## zarilla (21. Januar 2004)

Und Templateklassen können auch genau wie "normale" Klasse deklariert werdern ?
dh Klasse in .h und Methodendefinition in .cpp ?


----------



## chibisuke (21. Januar 2004)

Natürlich, wie willst du sie sonst deklarieren?

Bedenke nur, das man von Template klassen keine library oder DLL anlegen kann, ohne die klassen explizit für alle datentypen zu instanzieren für die man sie benutzen will.

grundsätzlich sieht das so aus:

headerdatei:

```
template <class T> class MyTemplateClass : public AnotherClass {
   public:
      T* getObject();
      //...
};
```
cpp datei:

```
template<class T> T* MyTemplateClass::getObject() {
   return new T();
}
```

Das sich diese klasse hier absolut nix bringt, is klar, aber das soll ja nur n beispiel sein


----------



## Tobiasm (22. Januar 2004)

Bist Du sicher, dass Templates in eine Cpp-Datei gehören? AFAIK gehören sie entweder direkt in den Header oder aber in eine Datei, die in den Header per #include "..." eingebunden wird.

Der Grund ist folgender: "When writing template classes, function definitions are usually stored in a header file along with their declarations, and not in a separate .cpp file. Trying to do otherwise typically will result in a linker error. This is because most compilers require template definitions to be available to each translation unit that uses them, through the inclusion of header files." (http://www.codeguru.com/atl/KD062002.html - Stand 22.01.04)

Ich weiß jetzt aber nicht, ob es schon weit verbreitete Compiler bzw. Linker (z.B. GCC) gibt, die das nicht mehr brauchen.

MfG

Tobias


----------



## zarilla (22. Januar 2004)

also ich habe es in Dev-C++ (GCC) folgendermaßen probiert: 
MyTemplateClass.h:

```
template <class T> class MyTemplateClass {
   public:
      MyTemplateClass(void);
      T* getObject();
      int size(void);
      //...
};
```
myTemplateClass.cpp:

```
#include "MyTemplateClass.h"

template<class T> T* MyTemplateClass::getObject() {
   return new T();
}
template<class T> MyTemplateClass::MyTemplateClass(void)
{
    cout<<"HELLO"<<endl;
}
template<class T> int MyTemplateClass::size(void)
{
    cout<<"Grösse: "<<sizeof(T)<<endl;
    return 0;
}
```
main.cpp:


```
#include <iostream>
#include <stdlib.h>
#include "MyTemplateClass.h"
using namespace std;

int main(void)
{
  MyTemplateClass<int> ttest();
  ttest.size(); 
  system("Pause");
  return 0; 
}
```

und es funktioniert irgendwie nicht...
16 main.cpp  request for member `size' in `ttest()', which is of non-aggregate 
Das Template std::Vector ist auch in der header-datei definiert. 
Aber ich zweifle irgendwie daran das alle Templatemethoden inline sein sollen !?


----------



## Tobiasm (22. Januar 2004)

Siehe mein Beitrag direkt über Deinem.

MfG

Tobias


----------



## zarilla (22. Januar 2004)

ja ok
aber wie dann ?
selbst das deklarieren im selben header funktioniert nicht.


----------



## chibisuke (23. Januar 2004)

> _Original geschrieben von Tobiasm _
> *Bist Du sicher, dass Templates in eine Cpp-Datei gehören? AFAIK gehören sie entweder direkt in den Header oder aber in eine Datei, die in den Header per #include "..." eingebunden wird.
> 
> Der Grund ist folgender: "When writing template classes, function definitions are usually stored in a header file along with their declarations, and not in a separate .cpp file. Trying to do otherwise typically will result in a linker error. This is because most compilers require template definitions to be available to each translation unit that uses them, through the inclusion of header files." (http://www.codeguru.com/atl/KD062002.html - Stand 22.01.04)
> ...



Also ich hab selbst schon Template klassen geschrieben und die funktionen in cpp dateien gepackt, funktioniert anstandslos...
Ich benutze VC++ 6.0 als Compiler.

Linkerfehler hatte ich erst als ich versucht hab die Template klasse in eine LIB zu packen, denn dann musste ich zuerst die klasse in der lib explizit instanzieren für jeden zu verwendenden datentyp.


----------



## Tobiasm (23. Januar 2004)

@chibisuke: Also, ich habe mit meinem VC++.NET ausprobiert die Definition der Funktionen in eine cpp-Datei auszulagern und nur die Definition der Klasse im Header zu lassen. Daraufhin habe ich die Fehlermeldung von dem Linker erhalten, dass die Funktionen, die ich ausgelagert hatte, nicht aufgelöst werden konnten. Außerdem kann ich mir schwer vorstellen, dass sich der VC++ 6 Compiler  da wesentlich anders verhält. Hast Du vielleicht die CPP-Datei vielleicht in die Header-Datei eingebunden oder hast Du explizite Template-Instanzierung genutzt ?

@zarilla: Hast Du mal


```
template<class T> T* MyTemplateClass<T>::getObject()
```

probiert. Vermutlich fehlt nur das <T> hinter MyTemplateClass.

MfG

Tobias


----------



## chibisuke (24. Januar 2004)

Anfangs weder noch, die Explizite Typeninstanzierung war erst erforderlich als ich eine lib draus erzeugt hab...

wie auch immer, ich halte nix davon methoden in H dateien zu schreiben, gibts nämlich gern ärger mit dem linker, weil er dann wenn man die mehrmals verwendet oft doppelt existieren und der linker dann nie weiß welche er benutzen soll.

Naja Egal, solange es funktioniert passt es.


----------



## Tobiasm (24. Januar 2004)

Kannst Du mal den Code posten (wenn er jetzt nicht geheim bzw. vertraglich geschützt ist) ? Jetzt interessiert es mich wirklich mal, wie Du das gemacht hast.

MfG

Tobias


----------



## zarilla (24. Januar 2004)

hab ich das richtig verstanden das  chibisuke template-methoden in cpp dateien definiert hat ?
dann darf diese cpp aber nicht mit kompiliert werden oder ?


----------



## Tobiasm (24. Januar 2004)

Nein, eigentlich nicht, den Grund hatte ich ja schon weiter oben geschrieben. Deshalb habe ich ja auch extra nach dem Quellcode gefragt, weil mich interessiert, wie er das gemacht hat.


----------



## chibisuke (25. Januar 2004)

Also ich würde dir ja das gesamte projekt als source geben, damit du es selbst kompilieren kannst, aber 1.) is das projekt mittlerweile 40MB reiner source, und 2.) sind große teile des codes aus sicherheitsgründen unter verschluss.(cryptographierechniken, übertragungsprotokolle, ..)

Die klasse von der ich rede is so simple,dass ich sie dir zeichen kann.

aus corelib.lib:


```
// -------------------------------------------------
// CHashtable.cpp
// -------------------------------------------------
// (c) 2003, BeamVision
// Alle Rechte vorbehalten 
// -------------------------------------------------

#include "../common/CHashtable.h"

///////////////////////////////////////////////////////////////
// TEMPLATE T: class to use as a class for the Hashtable
///////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////
// constructs the element
//
template <class T> CHashtable<T>::CHashtable() {
	this->data = new CArray();
}
   
///////////////////////////////////////////////////////////////
// every element entered in the hashtable is deleted
//    when it is removed
//
template <class T> CHashtable<T>::~CHashtable() {
	for(unsigned int i = 0; i < this->data->countItems(); i++) {
		if(this->data->GetItem(i) != NULL) {
			delete this->data->GetItem(i);
		}
	}
	delete this->data;
}

/////////////////////////////////////////////////////////////
// retrived a entry of the hashtable
// @param: the name of the assiciated object
// @return: Template type entry associated with the name
//
template <class T> T* CHashtable<T>::get(char* name) {
	CHashtableEntry<T> *tmp1;
	for(unsigned int i = 0; i < this->data->countItems(); i++) {
		if(this->data->GetItem(i) != NULL) {
			tmp1 = (CHashtableEntry<T>*)this->data->GetItem(i);
			if(_stricmp(tmp1->name, name) == NULL) {
				return (T*)((CHashtableEntry*)this->data->GetItem(i))->object;
			}
		}
	}
	return NULL; 
}

/////////////////////////////////////////////////////////////
// adds a new element to the Hashtable
// @param: name of the object, is duplicated afterwards
// @param: pointer to the object to insert, should be
//         allocated on the heap
//
template <class T> void CHashtable<T>::insert(char* name, T* obj) {
	this->data->AddItem(new CHashtableEntry<T>(obj, strdup(name)));	
}

/////////////////////////////////////////////////////////////
// removes and deletes a specified item from the 
//           hashtable
// @param: name of the element
//
template <class T> void CHashtable<T>::remove(char* name) {
	for(unsigned int i = 0; i < this->data->countItems(); i++) {
		if(this->data->GetItem(i) != NULL) {
			if(_stricmp(((CHashtableEntry*)this->data->GetItem(i))->name, name) == NULL) {
				delete ((CHashtableEntry*)this->data->GetItem(i));
				this->data->DeleteItem(i);
			}
		}
	}
}

////////////////////////////////////////////////////////////////
// contructs a new Hashtable entry, should not be
//        used by any other element then CHashtable and childs
// @param: object to insert
// @param: name to be duplicated and inserted
//
template <class T> CHashtableEntry<T>::CHashtableEntry(T* obj, char* name) {
	this->object = obj;
	this->name = _strdup(name);
}

////////////////////////////////////////////////////////////////
// this ctor is only for use in exceptional cases
//        it should not be used regularly
// 
template <class T> CHashtableEntry<T>::CHashtableEntry() {
	this->name = NULL;
	this->object = NULL;
}

////////////////////////////////////////////////////////////////
// destructs the element, and deletes any associated values
template <class T> CHashtableEntry<T>::~CHashtableEntry() {
	if(this->name) {
		delete this->name;
	}
	if(this->object) {
		delete this->object;
	}
}

/////////////////////////////////////////////////////////////////
// Create Virtual instance of CHashtable
//       this must be done 'cause we are working inside
//       a library.

template class CHashtable<char>;
template class CHashtable<_CObject>;
template class CHashtableEntry<char>;
template class CHashtableEntry<_CObject>;
```


```
#pragma once
// -------------------------------------------------
// CHashtable.h
// -------------------------------------------------
// (c) 2003, BeamVision
// Alle Rechte vorbehalten
// -------------------------------------------------

//TEMPLATE-CLASS

#include "CArray.h"
#include <string.h>
#ifndef NULL
#	define NULL 0
#endif

template <class T> class CHashtable :public _CObject {
	public:
		CHashtable();
		~CHashtable();

		T* get(char* name);
		void insert(char* name, T* obj);
		void remove(char* name);

	protected:
		CArray* data;
};

template <class T> class CHashtableEntry :public ::_CObject {
	public:
		CHashtableEntry();
		CHashtableEntry(T*, char*);
		~CHashtableEntry();

		T* object;
		char* name;
};
```

Während ich die klasse geschrieben und getestat hab hatte sie noch keine explizite instanzierung, und war in der haupt DLL enthalten. Nachdem die Tests abgeschlossen waren, kam sie in éine lib, was die explizite instanzierung erforderlich machte.seither wurde nichts mehr verändert.

Verwendung natürlich wie auch sonst üblich, header einbinden, CPP datei einfügen ins projekt, und los gehts...
eventuell ein typedef...wenn man zu faul ist jedesmal diese <T> anzugeben...

Der code stammt aus meinem aktuellen projekt Chimera-Crystals.


----------



## Tobiasm (26. Januar 2004)

Und was bindes Du dann ein ?  CHashtable.cpp oder CHashtable.h? Weil letzteres will bei mir add hoc nicht arbeiten.

MfG

Tobias


----------



## chibisuke (27. Januar 2004)

CHashtable.h natürlich

Ist ja die einzige datei die in ../common/ liegt die damit zu tun hatt...
Was anderes würde ja die struktur des projekte durcheinander bringen ;-)


----------

