2016-03-14 23 views

risposta

27

Ho bisogno di lanciare in qualche modo?

Sì, è possibile utilizzare static_cast.

static_cast può anche essere usato per disambiguare sovraccarichi di funzioni eseguendo una conversione da funzione a puntatore al tipo specifico, come in

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

Così si può:

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

Caro signore, è brutto. – cat

+2

Ogni volta che vedo la sintassi del tipo C++ provo l'impulso di scrivere qualcosa - qualsiasi cosa - in Haskell. – ApproachingDarknessFish

3

È necessario utilizzare un numero static_cast per disambiguare.

&test::error non è valutabile poiché la funzione è sovraccaricata. Il fatto che tu stia assegnando questo a qualcosa contrassegnato con auto non è immediatamente rilevante.

Una correzione sarebbe quella di utilizzare static_cast<int(test::*)()>(&test::error) o static_cast<void(test::*)(int)>(&test::error) come appropriato.

Quindi auto funzionerà poiché non vi sarà alcuna ambiguità nella deduzione del tipo.

34

È possibile specificare in modo esplicito il tipo di puntatore della funzione membro.

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

Siamo spiacenti, il mio commento è stato sbagliato. Più uno. – Bathsheba

+2

Questo; un cast non è specificamente necessario, tutto ciò che conta è che il compilatore sia in grado di disambiguare quale sovraccarico debba essere usato (e quindi quale tipo è desiderato). –

+0

Aggiungo che aggiungere un typedef renderebbe le cose ancora più leggibili: 'using error_func = int (test :: *)(); error_func f1 = & test :: error; '. – Synxis

1

Poiché è già stata fornita una risposta, presenterò una soluzione più semplice per gli occhi. Questa situazione è ideale per una macro se non si vuole scrivere il cast ogni volta:

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

Ecco la soluzione quando non si dispone di Internet per leggere la brutta funzione di puntatore-a -Membro sintassi:

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

Nota che fino ad ora si ottiene chiusure come i tipi e non puntatori a funzione. Se si desidera che i puntatori di funzione siano utili se si desidera archiviare funzioni membro diverse con la stessa firma in una matrice, è possibile eseguire la chiusura su un puntatore di funzione (normale) tramite + (vedere here).

Per quanto posso vedere al momento, con quanto sopra puoi fare concettualmente qualsiasi cosa tu possa fare con i puntatori funzione-membro, eccetto ovviamente chiamare una routine che richiede esattamente un tale puntatore. Ed è molto più bello.

Problemi correlati