2016-03-12 7 views
5

Sto usando macro asserzione da assert.h Ho definito lambda per eseguire il controllo dell'asserzione.Ottenere troppi argomenti forniti per l'errore di compilazione di una funzione simile a una macro durante la definizione di lambda all'interno assert (assert.h) in Xcode [C++]

int val1 = 0; 
int val2 = 1; 

const auto check = [val1,val2]()-> bool 
{ 
    return val1 < val2; 
}; 
// no error for this call 
assert(check() && "Test is failed"); 

// no error for this call 
assert([=]()-> bool 
     { 
      return val1 < val2; 
     }() && "Test is failed"); 
//compile error for this call "too many arguments provided to function-like macro invocation" 
assert([val1,val2]()-> bool 
     { 
      return val1 < val2; 
     }() && "Test is failed"); 

perché sto ottenendo

troppi argomenti addotti a funzionare come macro invocazione

errore di compilazione per il caso in cui sto usando asserire macro e definizione di lambda con più di un argomento nella lista di cattura?

risposta

5

Il problema è la virgola nell'elenco di acquisizione.

Il preprocessore ha una comprensione estremamente limitata della sintassi C++, principalmente la sostituzione di testo banale. Se una virgola non è compresa tra parentesi interna corrispondente (e non parte di un token come un letterale di stringa, ovviamente), il preprocessore lo tratterà come separatore di argomenti dell'invocazione di macro.

Quindi il preprocessore pensa di invocare asser con i due argomenti [this e il resto del materiale dietro la prima virgola, che produce l'errore.

È possibile risolvere questo errore utilizzando un ulteriore set di parentesi:

int i = -7, j = 7; 
assert(([i,j](){return i + j;}())); 

Per gli amanti standard:

La sequenza di token pre-elaborazione delimitate da all'esterno, più corrispondenti parentesi forma l'elenco degli argomenti per la macro simile alla funzione. I singoli argomenti all'interno dell'elenco sono separati dai token di preposizione della virgola , ma i token di preprocessing della virgola tra parentesi interne corrispondenti non separano gli argomenti . Se ci sono sequenze di token di preelaborazione all'interno dell'elenco di argomenti che altrimenti sarebbero come direttive di pre-elaborazione, 155 il comportamento non è definito.

16.3/11 in N4140, enfasi su miniera.

+0

Baum mit Augen ancora una cosa non chiara, l'argomento di assert in asert.h è dentro() '#define \t assert (e) \ (__builtin_expect (! (E), 0)? __assert_rtn (__ func__, __FILE__, __LINE__, #e): (void) 0) ' –

+1

@TM Quei paren arrivano troppo tardi, per la citazione di cui sopra, le parentesi e le virgole * prima * l'espansione sono rilevanti, non quelle nel risultato. –

2

Il preprocessore è molto semplice, vede tutte le virgole come separatori di argomenti.

Quindi non è possibile utilizzare una macro se si passa a qualcosa con una virgola come argomento della macro.

+0

Joachim Pileborg perché non genera errori di compilazione per altre virgole in caso di chiamata con [=]? –

+0

@TM Per essere brutalmente onesto, non penso che tu ci stia dicendo la verità. Il preprocessore non ha concetto o conoscenza dell'effettivo codice C++ o della sintassi C++, il preprocessore conosce solo il proprio linguaggio limitato, dove tutte le virgole in una "chiamata" di macro vengono utilizzate come separatori di argomenti. Pertanto non credo che il codice funzionerà e non ti darà un errore. –

+0

Joachim Pileborg ma funziona :) senza errori di compilazione Sto usando Xcode Versione 7.2.1 (7C1002) –