2016-03-14 12 views

Antwort

27

Muss ich irgendwie werfen müssen?

Ja, Sie können static_cast verwenden.

static_cast kann auch Funktion Überlastungen verwendet werden, um Mehrdeutigkeiten durch eine Funktion zu Zeiger Umstellung auf bestimmte Art durchgeführt wird, wie in

std::transform(s.begin(), s.end(), s.begin(), static_cast<int(*)(int)>(std::toupper));

So können Sie:

auto f1 = static_cast<int(test::*)()>(&test::error); 
auto f2 = static_cast<void(test::*)(int)>(&test::error); 
+29

Lieber Herr, das ist hässlich. – cat

+2

Jedes Mal, wenn ich C++ - Syntax sehe, verspüre ich den Drang, in Haskell etwas zu schreiben - irgendwas. – ApproachingDarknessFish

3

Sie müssen eine static_cast verwenden, um zu disambiguieren.

&test::error ist nicht auswertbar, da die Funktion überlastet ist. Die Tatsache, dass Sie dies einem Objekt zuweisen, das mit auto gekennzeichnet ist, ist nicht unmittelbar relevant.

Eine Lösung wäre, static_cast<int(test::*)()>(&test::error) oder static_cast<void(test::*)(int)>(&test::error) wie geeignet zu verwenden.

Dann auto funktioniert, da es keine Mehrdeutigkeit in der Typableitung gibt.

34

Sie können den Memberfunktionszeigertyp nur explizit angeben.

int (test::*f1)() = &test::error; 
void (test::*f2)(int) = &test::error; 
+0

Entschuldigung, mein Kommentar war falsch. Plus eins. – Bathsheba

+2

Dies; eine Umwandlung ist nicht speziell notwendig, es kommt nur darauf an, dass der Compiler in der Lage ist, zu disambiguieren, welche Überladung verwendet werden soll (und somit welcher Typ gewünscht wird). –

+0

Ich würde hinzufügen, dass das Hinzufügen eines typedef die Dinge noch mehr lesbarer machen würde: 'using error_func = int (test :: *)(); error_func f1 = & test :: fehler; '. – Synxis

1

Da eine Antwort bereits gegeben ist, werde ich eine Lösung vorstellen, die die Augen schont. Diese Situation ist für einen Makro, wenn Sie wollen, jedes Mal wenn die Besetzung nicht schreiben:

template<class T> 
using test_type_t = T test::*; 
#define TEST_CAST(T, F) static_cast<test_type_t<T>>(&F) 

auto f1 = TEST_CAST(void(int), test::error); 
1

Hier ist die Lösung, wenn Sie den hässlichen Funktion-Zeiger auf das Internet nicht haben zu lesen, -Mitgliedsyntax:

auto err1 = [](test& t) { return t.error(); }; 
auto err2 = [](test& t, int x) { return t.error(x); }; 

Beachten Sie, dass Sie bis jetzt Schließungen als Typen und keine Funktionszeiger erhalten. Wenn Sie Funktionszeiger verwenden möchten, die nützlich sind, wenn Sie verschiedene Elementfunktionen mit derselben Signatur in einem Array speichern möchten, können Sie den Abschluss über + (siehe here) an einen (normalen) Funktionszeiger übergeben.

Soweit ich im Moment sehen kann, mit dem oben genannten können Sie konzeptionell alles tun, was Sie tun können mit Funktion-zu-Mitglied-Zeiger - außer natürlich Aufruf einer Routine, die genau einen solchen Zeiger benötigt. Und es ist viel schöner.