2010-10-21 15 views
10

Come si confrontano due funzioni lambda in C++ (Visual Studio 2010)?Operatore lambda C++ ==

std::function<void()> lambda1 = []() {}; 
std::function<void()> lambda2 = []() {}; 
bool eq1 = (lambda1 == lambda1); 
bool eq2 = (lambda1 != lambda2); 

Viene visualizzato un errore di compilazione che afferma che l'operatore == non è accessibile.

MODIFICA: Sto provando a confrontare le istanze di funzione. Quindi lambda1 == lambda1 dovrebbe restituire true, mentre lambda1 == lambda2 dovrebbe restituire false.

+1

Stai cercando di confrontare il risultato della valutazione dei lambda o degli stessi lambda? –

+0

Cosa intendi per ==? Che cosa testate uguali?E se mai lo sapessi, come potrebbe il compilatore sapere da solo e scegliere un operatore == che farebbe ciò che non sai? –

+2

@Joshua: Sta ovviamente cercando di confrontare i lambda stessi. Qual è una cosa perfettamente ragionevole da fare per chiunque provenga da una lingua con oggetto di funzione di prima classe "corretto", in lambda o qualsiasi altra notazione. Sebbene tali lingue possano o no concordare sul fatto che 'labda1' e' lambda2' nel codice precedente siano uguali, quindi Stephane probabilmente ha sottolineato perché C++ 0x ha lasciato fuori 'operator ==' per lambdas. –

risposta

12

Non è possibile confrontare gli oggetti std::function perché std::function is not equality comparable. Anche il tipo di chiusura della lambda non è paragonabile alla parità.

Tuttavia, se il lambda non cattura nulla, lambda stessa può essere convertito in un puntatore a funzione, e puntatori a funzione sono l'uguaglianza paragonabili (tuttavia, al meglio della mia conoscenza è del tutto specificato se in questo esempio are_1and2_equal è true o false):

void(*lambda1)() = []() { }; 
void(*lambda2)() = []() { }; 
bool are_1and1_equal = (lambda1 == lambda1); // will be true 
bool are_1and2_equal = (lambda1 == lambda2); // may be true? 

Visual C++ 2010 does not support this conversion. La conversione non è stata aggiunta a C++ 0x fino a poco prima che Visual C++ venisse rilasciato.

-3

Risposta più semplice: Tutti gli operatori di funzione di classe <> ==() s sono privati.

Followup domanda: Che se la seguente ti aspettavi:
- confrontare l'indirizzo di funzioni
- confrontare due oggetti distinti (di tipo std :: funzione < void()>
- confrontare due funzioni astratte

Edit (quasi 5 anni più tardi):

trovo divertente che ci sono downvotes senza commenti Se i downvotes sono causa C++ 11 ha cambiato il livello di accesso per la funzione std :: :: operator ==(). , quindi dico che l'elettore non capisce come funziona il tempo i downvotes sono perché il questionario non ha chiarito cosa avrebbe immaginato l'operatore ==(), forse l'elettore dovrebbe vedere la discussione di più ore tramite commenti immediatamente sotto la domanda, che l'OP ha risposto solo nei commenti a la mia risposta.

+0

Il primo: confronta l'indirizzo delle funzioni. –

+0

C++ 11 non ha modificato il livello di accesso per 'std :: function :: ', perché 'std :: function' non esisteva in C++ 03. Inoltre, 'operator ==' * non è * privato (in qualsiasi versione dello standard); non è * nemmeno una funzione membro *. E non confronta gli indirizzi delle funzioni; permette solo il confronto con 'nullptr'. –

+0

Quindi devo essere stato sensitivo poiché l'ho fatto riferimento circa 10 mesi prima che C++ 11 fosse finalizzato. In alternativa, si tratta di un riferimento a TR1 (2007) e si sta confermando il contenuto della mia modifica: non si capisce come funziona il tempo. –

2

Non è possibile confrontare le funzioni, fine di.

Si può al massimo confrontare i puntatori a funzioni in lingue che hanno quel concetto (questo è anche ciò che, per esempio, EQ fa in Lisp. E non riesce per funzioni equivalenti che non occupano lo stesso posto in memoria.)

+2

+1. Il confronto di lambda potrebbe funzionare in alcune lingue sulla base di hashing dei loro alberi di analisi (o di realizzare lo stesso "per sbaglio" attraverso la memoizzazione e il confronto dei loro indirizzi), ma ci sono poche basi matematiche per tale operazione. Determinare che due funzioni arbitrarie facciano la stessa cosa è impossibile. Le funzioni vuote sono un caso molto speciale. – Potatoswatter

+2

Esistono due concetti di uguaglianza per le funzioni: uguaglianza di definizione e uguaglianza di comportamento. Il primo potrebbe essere fatto confrontando il testo del programma in un certo senso (il confronto tra l'indirizzo di implementazione è una variazione su questo) ma il secondo è impossibile; il confronto intenzionale completo è esattamente nella stessa palude computazionale del problema di interruzione. –

+0

@Potatoswatter Ma il compilatore conosce il tipo di lambda e lambdas ha tipi univoci, quindi potrebbe fornire 'operator ==' per lambdas dello stesso tipo - perché sono lo * stesso lambda *. L'operatore stesso restituire 'true' IFF gli stessi valori (bit a bit, presumibilmente) vengono catturati da ogni lambda. –

0

Questo è impossibile.

Proof schizzo: se fosse possibile calcolare

f1 == f2 

allora sarebbe anche possibile calcolare

f == infiniteLoop 

e risolvere il problema Halting.

+0

Non so se sei serio, ma questo non ha senso. Due fonti/binari/script/corpi di funzioni/... possono essere facilmente confrontati (diciamo nell'IR normalizzato/ottimizzato del compilatore), ma questo non risolve il problema di interruzione. Si può al massimo controllare se la sorgente/funzione data/... è uguale a una nota che si arresta. –

+1

Mentre sono d'accordo che è impossibile determinare che due funzioni siano la stessa funzione * nel caso generale *, un'eguaglianza più debole, due funzioni che hanno lo stesso codice (tabella di stato di Turing, se lo si desidera) sono uguali. Un'equivalenza ancora più debole (che potrebbe lasciare l'esempio dell'OP non equo) sarebbe che si confrontassero uguali se fossero lo stesso oggetto funzione, che è fondamentalmente uguale al confronto dei puntatori di funzione. – SingleNegationElimination

+0

@Matteo Italia, @TokenMacGuy: L'OP non specifica quale tipo di uguaglianza sta cercando, quindi sto assumendo l'uguaglianza estensionale, che sembra essere la solita definizione. Se l'OP desidera una definizione * insolita *, deve fornirne uno. –