| Autor |
Nachricht |
Nash26
Mitglied
Benutzerprofil
Anmeldungsdatum: 12.10.2009
Beiträge: 32
|
Nash26 Mitglied
20:59:23 08.08.2012 Titel: |
Check für is member function pointer |
Zitieren |
Hi zusammen,
ich suche einen Methode mit der ich überprüfen kann ob ein Type T ein Member function ptr is oder nicht.
also sowas in der form
is_member_function_ptr<void (MyClass::*)(void)>::value => true
is_member_function_ptr<void (*)(int)>::value => false da function
Das ganze muss mit C++03 funktionieren, VS + gcc
Boost kann ich leider nicht verwenden.
Hat jemand ne idee?
Das ich SFINAE verwenden muss ist klar, aber ich möchte ungern eine substitution für alle mögliche argument variationen niederschreiben.
Was denkt ihr? |
|
|
|
 |
arogmyxdfa
Unregistrierter
|
arogmyxdfa Unregistrierter
21:57:40 08.08.2012 Titel: |
|
Zitieren |
| C++: | template <class T> bool is_mfun (T* ) { return false; }
template <class C, class T> bool is_mfun (T C::*) { return true; } | | |
|
|
|
 |
wxSkip
Mitglied
Benutzerprofil
Anmeldungsdatum: 16.11.2009
Beiträge: 1985
|
wxSkip Mitglied
23:16:03 08.08.2012 Titel: |
|
Zitieren |
| arogmyxdfa schrieb: | | C++: | template <class T> bool is_mfun (T* ) { return false; }
template <class C, class T> bool is_mfun (T C::*) { return true; } | |
|
Das prüft lediglich, ob du einen Pointer auf einen Member hast, nicht einen Pointer auf eine Memberfunktion. Zudem wird es einen Fehler bei allen Nicht-Pointer-Aufrufen geben...
@Nash26:
Tja, ohne Variadic Templates wird dir wohl nichts anderes übrig bleiben, als is_member_function_ptr für eine ausreichende Anzahl an Parametern zu spezialisieren:
| C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | template<typename T> struct is_member_function_ptr
{
static const bool value = false;
};
template<typename Ret, typename Class> struct is_member_function_ptr<Ret (Class::*)()>
{
static const bool value = true;
};
template<typename Ret, typename Class, typename T1> struct is_member_function_ptr<Ret (Class::*)(T1)>
{
static const bool value = true;
};
template<typename Ret, typename Class, typename T1, typename T2> struct is_member_function_ptr<Ret (Class::*)(T1, T2)>
{
static const bool value = true;
};
//... | | |
_________________ Je mehr Käse, desto mehr Löcher. Je mehr Löcher, desto weniger Käse. Also: Je mehr Käse, desto weniger Käse!
|
|
 |
camper
Mitglied
Benutzerprofil
Anmeldungsdatum: 06.08.2004
Beiträge: 5794
|
camper Mitglied
00:29:16 09.08.2012 Titel: |
|
Zitieren |
| wxSkip schrieb: | | arogmyxdfa schrieb: | | C++: | template <class T> bool is_mfun (T* ) { return false; }
template <class C, class T> bool is_mfun (T C::*) { return true; } | |
|
Das prüft lediglich, ob du einen Pointer auf einen Member hast, nicht einen Pointer auf eine Memberfunktion. | Nicht ganz, auch Zeiger-auf-non-const-Memberfunktionen sind erfasst (in diesem Fall wird T als Funktionstyp deduziert). |
|
|
|
 |
Nash26
Mitglied
Benutzerprofil
Anmeldungsdatum: 12.10.2009
Beiträge: 32
|
Nash26 Mitglied
08:14:14 09.08.2012 Titel: |
|
Zitieren |
Kennt ihr das Buch C++ Templates the complete guide?
Dort schreibt der Autor das es auch ohne die vielen parameter variationen geht:
Hier benutzt er es um zu überprüfen ob eine Funktion gegeben ist oder nicht.
http://www.josuttis.com/tmplbook/functors/typet.hpp.html
@arogmyxdfa
bei anderen typen soll es aber nicht zum compile Fehler kommen |
|
|
|
 |
pumuckl
Moderator
Benutzerprofil
Anmeldungsdatum: 21.06.2005
Beiträge: 7326
|
pumuckl Moderator
10:33:25 09.08.2012 Titel: |
|
Zitieren |
|
 |
knivil
Mitglied
Benutzerprofil
Anmeldungsdatum: 11.02.2009
Beiträge: 5861
|
knivil Mitglied
10:44:27 09.08.2012 Titel: |
|
Zitieren |
Nicht ganz das, was du suchst, aber vielleicht enthaelt es Anregungen: http://stackoverflow.com/ ....... ent-has-a-member-function
Die Frage ist natuerlich, warum du das brauchst! |
_________________ If it were not for laughter, there would be no Tao.
Sie können einen Beitrag nicht so schnell nach Ihrem letzten absenden, bitte warten Sie einen Augenblick.
Zuletzt bearbeitet von knivil am 10:45:52 09.08.2012, insgesamt 1-mal bearbeitet |
|
 |
camper
Mitglied
Benutzerprofil
Anmeldungsdatum: 06.08.2004
Beiträge: 5794
|
camper Mitglied
11:30:01 09.08.2012 Titel: |
|
Zitieren |
| Nash26 schrieb: | Kennt ihr das Buch C++ Templates the complete guide?
Dort schreibt der Autor das es auch ohne die vielen parameter variationen geht:
Hier benutzt er es um zu überprüfen ob eine Funktion gegeben ist oder nicht.
http://www.josuttis.com/tmplbook/functors/typet.hpp.html
@arogmyxdfa
bei anderen typen soll es aber nicht zum compile Fehler kommen | Dann hast du doch schon eine Lösung.
In C++03 gibt es keine schöne Lösung dafür, da es keine Möglichkeit gibt, den Typ von Memberfunktionszeiger generisch aufzuschreiben (mangels variadic templates).
Es bleiben zwei Alternativen:
1. viele Spezialisierungen für ausreichend viele Parameter, Nachteil: eine Menge Codeduplikation, folglich langsames Compilieren, nicht allgemeingültig, falls doch mal längere Parameterlisten benötigt werden
2. durch Eliminierung, wenn alle anderen Typen ausgeschlossen werden, muss ein Memberfunktionszeiger übrig bleiben, Nachteil: funktioniert ggf. nicht mehr, wenn weitere Typen dazukommen, die usprünglich nicht existierten (Compilererweiterungen, neue Standards...).
Das Testen auf non-const-non-volatile-Memberfunktionszeiger ist einfach. Schwierigkeiten machen nur const,volatile und const volatile-Memberfunktionen:
| C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | template <bool b> struct bool_ { static const bool value = b; };
typedef bool_<false> false_type;
typedef bool_<true> true_type;
template <typename T, typename U> struct is_same : false_type {};
template <typename T> struct is_same<T, T> : true_type {};
template <typename T> struct is_function : is_same<void(T),void(T*)> {};
// Spezialisierungen für Typen, für die void(T) oder void(T*) ill-formed ist:
// leidet unter dem gleichen Problem wie 2., weil auch für rvalue-Referenzen spezialisiert werden müsste; kann man durch den sizeof-SFINAE-Trick in den Griff kriegen, ist mir aber hier zuviel Schreibarbeit
template <> struct is_function<const void> : false_type {}; //
template <> struct is_function<volatile void> : false_type {}; // kann nicht als Funktionsparameter auftreten (da immer unvollständig), die Sonderregel gilt nur für unqualifiziertes void
template <> struct is_function<const volatile void> : false_type {}; //
template <typename T> struct is_function<T&> : false_type {}; // kann keine Zeiger auf Referenzen bilden
template <typename T> struct is_mem_fun_ptr : false_type {};
template <typename T, typename C> struct is_mem_fun_ptr<T C::*> : is_function<T> {}; | | |
Zuletzt bearbeitet von camper am 12:22:36 09.08.2012, insgesamt 6-mal bearbeitet |
|
 |
Nash26
Mitglied
Benutzerprofil
Anmeldungsdatum: 12.10.2009
Beiträge: 32
|
Nash26 Mitglied
20:17:07 09.08.2012 Titel: |
|
Zitieren |
ist ja interesant, dein code funktioniert. Prima.
| Code: | | template <typename T, typename C> struct is_mem_fun_ptr<T C::*> : is_function<T> {}; | |
Aber warum wird diese spezialisierung instanziert, obwohl ich ein ein type mit 10 parametern übergebe?
Soweit ich das jetzt verstehe, brichst du das ganze schnell runter zu einem
test für is_function_ptr.
Das hier verstehe ich leider nicht:
| Code: | | template <typename T> struct is_function : is_same<void(T),void(T*)> {}; | | |
|
|
|
 |
camper
Mitglied
Benutzerprofil
Anmeldungsdatum: 06.08.2004
Beiträge: 5794
|
camper Mitglied
20:50:45 09.08.2012 Titel: |
|
Zitieren |
| Nash26 schrieb: | ist ja interesant, dein code funktioniert. Prima.
| Code: | | template <typename T, typename C> struct is_mem_fun_ptr<T C::*> : is_function<T> {}; | |
Aber warum wird diese spezialisierung instanziert, obwohl ich ein ein type mit 10 parametern übergebe? | Weil T selbst ein Funktionstyp sein kann. Und das passiert genau dann, wenn du das Template mit einem Zeiger auf non-const-non-volatile-Memberfunktion fütterst.
Nimmst du in den Deklarator ::* weg, bleibt ein Funktionstyp stehen. Leider können auf diese weise const und volatile Memberfunktionen nicht verarbeitet werden, weil Funktionstypen nicht qualifiziert sein dürfen (eine Einschränkung, für die mehr der Grund nie ganz klar geworden ist; dass Funktionen selbst nie qualifiziert sind, muss ja nichts mit dem Typen zu tun haben). Das führt zu der kuriosen Eigenschaft dass in z.B.
nach Wegnahme des Deklarator ::* etwas steht, was kein (legaler) Typ ist. Da Deklaratoren aber eigentlich einen Typ aus einem anderen ableiten, ist das in meinem Augen seltsam.
| Nash26 schrieb: | Das hier verstehe ich leider nicht:
| Code: | | template <typename T> struct is_function : is_same<void(T),void(T*)> {}; | |
| Der Test basiert auf den Besonderheiten die für die Deklarationen von Funktionsparametern gelten. Wird ein Funktionsparameter als Funktionstyp deklariert, so transformiert der Compiler das in eine Deklaration eines Funktionszeigers als Parameter (analog für Arrays, allerdings ist das Ergebnis der Transformation dort nicht ein Zeiger auf das Array sondern einer auf den Elementtyp). Es spielt also bei Funktionenparametern keine Rolle, ob ausdrücklich ein Zeiger deklariert wird, die Deklaration verweist trotzdem auf den selben Typ. Und das gilt so nur für Funktionstypen.
Dein verlinkter Code nutzt übrigens die gleiche Eigenschaft, nur wird hier der sizeof-Überladungstrick angewendet. |
Zuletzt bearbeitet von camper am 20:52:06 09.08.2012, insgesamt 1-mal bearbeitet |
|
 |
|
Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben. Sie können auf Beiträge in diesem Forum antworten. Sie können Ihre Beiträge in diesem Forum nicht bearbeiten. Sie können Ihre Beiträge in diesem Forum nicht löschen. Sie können an Umfragen in diesem Forum nicht mitmachen.
|
|
|
|
|