Parametertyp von Templatefunktion feststellen
-
Hi, ist es möglich festzustellen, ob der Funktionsparameter einer Templatefunktion ein Objekt/Referenz/Pointer ist? Also z.B. sowas:
template <class TParam>
void MyClass<TParam>::MyFunction(const TParam& param)
{
if (IsPointer(param))
{
}
elseif (IsReference(param))
{
}
else
{
}
}
-
template <class TParam> void MyClass<TParam>::MyFunction(const TParam& param) { if (IsPointer(param)) { } elseif (IsReference(param)) { } else { } }
-
Wozu brauchst du denn sowas? Erscheint mir äußerst suspekt.
-
Es gibt in C++ (seit C++11 auch im Standard) Type-Traits, definiert im Header
<type_traits>, mit denen geht das ganz einfach:-
std::is_reference<param>::value
(Achtung!
is_referencebeachtet LValue und RValue-Referenzen. -
std::is_pointer<param>::value -
std::is_object<param>::value
Nicht wahr für Typen wie Funktionen (aber wahr für Funktionszeiger), Referenzen, usw.
Allerdings - wie out schon angemerkt hat - wofür brauchst du das? Siehe in meiner Signatur das XY-Problem. Das hast du gerade.
-
-
template <class TParam> void MyClass<TParam>::MyFunction(TParam const* param) { // Zeiger } template <class TParam> void MyClass<TParam>::MyFunction(TParam const& param) { // Referenz }Die Suggeration vom Sohne geht erst mit static-ifs.
-
Es geht darum, dass ich nicht kopierbare Objekte habe (z.B. GUI-Controls). Also kann ich diese nicht als Objekt in einer Hashmap ablegen, sondern nur einen Pointer auf diese. In meiner generischen Hashmap-Klasse habe ich aber nun das Problem, dass ich aus den Zeigern einen Hash erzeugen können muss bzw. erkennen können muss, ob es ein Zeiger oder Objekt ist. Denn die Objekte haben alle eine GetHash-Funktion. Auf einen Zeiger kann ich diese nur leider nicht anwenden.
-
Die einzige Möglichkeit die ich im Moment sehe ist die Möglichkeit der Hashmap-Klasse einen custom "Comparer" als Parameter zu übergeben. Ich würde dann einen "PointerComparer" schreiben der die Zeigers als Keys miteinander vergleicht und zudem aus einem Key auch einen Hash berechnen würde. Analog gäbe es dann für richtige Objekte einen "ObjectComparer".
-
Auch das geht. Aber du willst auch das nicht.
Wenn du schon einen Pointer hast => DAS IST DEIN HASH!!! Deine Hashfunktion ist garantiert schlechter als ein Pointer, der 1. garantiert unique und 2. ohne Berechnung verfügbar ist.
Noch besser ist allerdings <boost/unordered_map> oder <tr1/unordered_map> oder <unordered_map> (C++11) einzubinden und davon zu profitieren. Da ist dein Hashproblem schon gelöst.
-
deinvater schrieb:
Die Suggeration vom Sohne geht erst mit static-ifs.
Ähm...nein!?
-
Nathan schrieb:
deinvater schrieb:
Die Suggeration vom Sohne geht erst mit static-ifs.
Ähm...nein!?
Zeig mal wie du das ohne Dispatch machst.
-
Na mit ifs?
http://ideone.com/YI1x5J
-
Das war ja auch meine Idee. Da die Adresse des Zeigers einmalig ist. Aber wie stelle ich das jetzt an? Folgende Funktion:
template <class TKey, class TValue> void HashMap<TKey, TValue>::Add(const TKey& key, const TValue& value) { ... int hashCode = /* hier brauche ich den HashCode*/ & 0x7fffffff; ... }Woher bekomme ich nun den HashCode bzw. woher weiß ich, dass "key" ein Zeiger oder Objekt ist?
-
Aha. http://ideone.com/xLjXxZ. Schonmal an den Fall vom OP gedacht?
-
Ja, du wirst so nicht arbeiten können, denn der Code wird nun einmal - sobald das Template instantiiert wird - komplett geschluckt und geprüft.
Wenn du bei Memberfunktionen in Klassentemplates Unterscheidung für mehrere verschiedenen Template-Parameter haben willst, nutze einen Trick. Das Int-To-Type Idiom.
Das ist eine hingekotzte Version, das geht bestimmt schöner:
#include<iostream> template<typename TParam> class MyClass { /// Definition für Referenzen void MyFunction( TParam const&, std::integral_constant<bool, false>, std::integral_constant<bool, true> ); /// Definition für Zeiger void MyFunction( TParam const&, std::integral_constant<bool, true>, std::integral_constant<bool, false> ); public: void MyFunction( TParam const& param ) { MyFunction(param, std::integral_constant<bool, std::is_pointer<TParam>::value>(), std::integral_constant<bool, std::is_reference<TParam>::value>()); } }; template <class TParam> void MyClass<TParam>::MyFunction(const TParam& param, std::integral_constant<bool, false>, std::integral_constant<bool, true>) { param << "Lol"; } template <class TParam> void MyClass<TParam>::MyFunction(const TParam& param, std::integral_constant<bool, true>, std::integral_constant<bool, false>) { (*param) << "Lol"; } int main() { MyClass<std::ostream*>().MyFunction(&std::cout); MyClass<std::ostream&>().MyFunction(std::cout); }Edit: Jup, hier wird das schöner gemacht - sieh dir das Beispiel an: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Int-To-Type
-
deinvater schrieb:
Wenn du schon einen Pointer hast => DAS IST DEIN HASH!!!
Das heißt, für gleiche Pointees gibt es unterschiedliche Hashwerte? Lol!
-
template <typename T> int getHashCode(T* t) { return reinterpret_cast<long>(t); } template <typename T> int getHashCode(T& t) { return t.getHashCode(); } struct S {int getHashCode()const{return 0;}}; int main() { S s; getHashCode(s); getHashCode(&s); }
-
deinvater schrieb:
Aha. http://ideone.com/xLjXxZ. Schonmal an den Fall vom OP gedacht?
Nö.
Nur bis "wie kann ich zwischen Pointer und nicht Pointer unterscheiden gelesen". Und das geht so.
*duck und weg*Edit:
Sone schrieb:
deinvater schrieb:
Wenn du schon einen Pointer hast => DAS IST DEIN HASH!!!
Das heißt, für gleiche Pointees gibt es unterschiedliche Hashwerte? Lol!
Schaue dir mal die std::hash<T*> Implementierung deines Compilers an. Oh.
-
Sone schrieb:
deinvater schrieb:
Wenn du schon einen Pointer hast => DAS IST DEIN HASH!!!
Das heißt, für gleiche Pointees gibt es unterschiedliche Hashwerte? Lol!
Es handelt sich um "nicht kopierbare Objekte habe (z.B. GUI-Controls)". Für nicht kopierbare Objekte ist die Identität an den Speicher gekoppelt. Ohne Ausnahme.
-
Upsi, ich habe mich vertan, ich dachte an was anderes, du hast Recht

Sone schrieb:
" 9
Sone schrieb:
deinvater schrieb:
Wenn du schon einen Pointer hast => DAS IST DEIN HASH!!!
Das heißt, für gleiche Pointees gibt es unterschiedliche Hashwerte? Lol!
Schaue dir mal die std::hash<T*> Implementierung deines Compilers an. Oh.
Schon klar. Ich habe das völlig missverstanden, ich dachte es ging um was anderes. Natürlich ist der Hash eines Zeigers sein Wert.
So wie halt für jeden Skalar sein Wert sein Hash ist.
-
Sone schrieb:
std::integral_constant<bool, true>, std::integral_constant<bool, false> std::integral_constant<bool, std::is_pointer<TParam>::value>(), std::integral_constant<bool, std::is_reference<TParam>::value>());lol?
1. std::true_type/std::false_type
2. typename std::is_pointer<T>::type/typename std::is_reference<T>::type