Template, Objekt/Pointer unterscheiden..
-
tpl schrieb:
Die folgende Klasse wird unterschiedlich, mit ItemHandle<x> oder mit
ItemHandle<x*> instanziert, was auch so bleiben soll. Allerdings habe
ich dadurch das Problem, daß der Konstruktor einmal element.bbox()
und einmal element->bbox() aufrufen müßte. Gibt es eine Möglichkeit
zu unterscheiden, ob da ein Pointer oder eine Klasse hereinkommt?template<class T_Item> class ItemHandle { public: ItemHandle(const T_Item& element_); private: Bbox itemBB; }; template<class T_Item> ItemHandle<T_Item>::ItemHandle(const T_Item& element_) : itemBB(element.bbox()) { } }..danke!
template <typename T> struct is_pointer_type { enum { value = false }; }; template <typename T> struct is_pointer_type<T*> { enum { value = true }; }; template <typename T> bool is_pointer(const T&) { return is_pointer_type<T>::value; }Dann anwenden :xmas1:
http://ideone.com/ESMtM#view_edit_box
Geprüft (atschibätsch PI).
-
Hacker schrieb:
template <typename T> struct is_pointer_type { enum { value = false }; }; template <typename T> struct is_pointer_type<T*> { enum { value = true }; }; template <typename T> bool is_pointer(const T&) { return is_pointer_type<T>::value; }Dann anwenden :xmas1:
http://ideone.com/ESMtM#view_edit_box
Geprüft (atschibätsch PI).
Geil! Das sollte die Lösung sein, ich werds gleich probieren. Ich kann mich
jetzt auch erinnern, daß ich davon mal gelesen habe, und zwar in Alexandrescu's
Modern C++ Design.Danke fürn Hinweis!
-
Hm, das war jetzt doch nicht die Lösung, denn is_pointer() generiert einen
Wert, aber was ich brauche, ist eine Unterscheidung zur Compile-Zeit, dennif(is_pointer(a)) a->bbox(); else a.bbox();compiliert natürlich nicht. Wie könnte man denn die vorgeschlagene
Spezialisierung syntaktisch umsetzen? Ich habe Beispiel gefunden, wo
man für einen festen Typ spezialisiert, aber wie denn, wenn der Typ
ein Template-Parameter ist wie in diesem Fall?
-
Bei einzelnen Funktionen mit Überladung:
template <typename T> void do_stuff(T* obj) { // Zeigervariante } template <typename T> void do_stuff(T& obj) { // Referenzvariante }Bei Klassen mithilfe einer Spzialisierung:
template <typename T> struct foo { ... }; template <typename T> struct foo<T*> { ... };Ich kann mir nicht vorstellen, dass Hackers Ding da irgendwie ne Hilfe ist. Zumal es das Ding sowieso schon unter std::is_pointer in <type_traits> gibt.
Edit: Und in deinem Fall würde ich einfach einen zweiten Ctor basteln, der einen const T* nimmt.
Edit 2: Achso, ich seh schon das Problem. Ist schon etwas spät

Ich würde wohl zwei Ctoren schreiben, die so aussehen:ItemHandle(typename std::remove_pointer<T>::type* ptr); ItemHandle(typename std::remove_pointer<T>::type& ref);
-
template <typename T> struct pointersensitiv { pointersensitiv(T a) {a.foo();} }; template<typename T> struct pointersensitiv<T*> { pointersensitiv(T* a) {a->foo();} }; #include<iostream> struct nur_zum_test { void foo() {std::cout << "Foo!\n";} }; int main() { nur_zum_test bar; pointersensitiv<nur_zum_test> objekt(bar); pointersensitiv<nur_zum_test*> pointer(&bar); }
-
template <typename T> T&& deref(T&& v) { return std::forward<T>(v); } template <typename T> T& deref(T* v) { return *v; }und dann einfach überall, wo a.foo() oder a->foo() auftauchen würde:
deref(a).foo()schreiben.
-
@SeppJ
Buääääääh, Konstruktoren als Funktionen misbrauchen ist mir ein Gräul
-
camper schrieb:
template <typename T> T&& deref(T&& v) { return std::forward<T>(v); } template <typename T> T& deref(T* v) { return *v; }und dann einfach überall, wo a.foo() oder a->foo() auftauchen würde:
deref(a).foo()schreiben.
Danke, das war die Lösung.
Die erste Funktion mußte ich aber anpassen:template <typename T> T& deref(T& v) { return v; } template <typename T> T& deref(T* v) { return *v; }was sollte denn das T&& deref(T&& v) bedeuten?
-
campers Lösung hat sowohl LValues als auch RValues geschluckt. Deine nimmt nur LValues. Stichwörter: Perfect Forwarding, Reference Collapsing.
-
314159265358979 schrieb:
Stichwörter: Perfect Forwarding, Reference Collapsing.
Und vor allem Anderen Stichwort C++11 und Rvalue-Referenzen. Wenn du das anpassen musstest, kann dein Compiler das wohl noch nicht.
-
pumuckl schrieb:
314159265358979 schrieb:
Stichwörter: Perfect Forwarding, Reference Collapsing.
Und vor allem Anderen Stichwort C++11 und Rvalue-Referenzen. Wenn du das anpassen musstest, kann dein Compiler das wohl noch nicht.
Ah, gcc version 4.5.2, und die Software soll am Ende auch noch auf VS 2008
compilieren. Daher habe ich es mit C++11 gar nicht eilig
Danke allen für die Hinweise, das Problem ist nun gut gelöst.
-
Beim GCC brauchst du nur beim kompilieren -std=c++0x angeben.
-
hustbaer schrieb:
@SeppJ
Buääääääh, Konstruktoren als Funktionen misbrauchen ist mir ein Gräul
Mir auch. Der Threadersteller hat aber ausdrücklich danach gefragt. Wenn du schnell gewesen wärst, hättest du vor dem edit noch eine Version mit normalen Funktoren gesehen.
-
314159265358979 schrieb:
Beim GCC brauchst du nur beim kompilieren -std=c++0x angeben.
Oder, wie bei mir (wie schon bei unserer Spielwiese festgestellt):
-std=gnu++0x
-
Zuletzt bearbeitet von Hacker am 16:01:35 17.12.2011, insgesamt 1-mal bearbeitet
Um uns das mitzuteilen musstest du den Thread nochmals ausgegraben?
-
h4xx02 schrieb:
Zuletzt bearbeitet von Hacker am 16:01:35 17.12.2011, insgesamt 1-mal bearbeitet
Um uns das mitzuteilen musstest du den Thread nochmals ausgegraben?
1. Falsches Deutsch,
2. Ja. Denn bei mir z.B. klappt das anders nicht, und wenn dich der Thread nervt dann ignorier ihn verdammt nochmal. Dadurch das du (und eig. ich auch) ihn weiter befüllen bleibt er ausgegraben. :xmas1: