2016-03-10 27 views
6

Dato this test program:Perché questa "chiamata" asserisce di vedere due argomenti invece di uno solo?

#include <cassert> 
#include <string> 
#include <type_traits> 

const std::string& const_string = "bla"; 
std::string const & string_const = "blabla"; 

static_assert(std::is_same<decltype(const_string), decltype(string_const)>::value, "Uhoh"); 

int main() 
{ 
    assert(std::is_same<decltype(const_string), decltype(string_const)>::value); 
} 

che afferma che due tipi sono le stesse al momento della compilazione e in fase di esecuzione utilizzando affermare di C. Tutti Clang, MSVC2015, e GCC riportano lo stesso errore, quindi sono abbastanza sicuro it's me:

main.cpp:13:49: error: too many arguments provided to function-like macro invocation 
    assert(std::is_same<decltype(const_string), decltype(string_const)>::value); 
               ^
/usr/include/assert.h:91:10: note: macro 'assert' defined here 
# define assert(expr)             \ 
     ^

Sono solo non vedendo due argomenti nel assert. Inoltre, lo static_assert funziona bene ... Quindi cosa sta succedendo qui?

+0

Credo che il preprocessore veda due "confronti"; 'std :: is_same :: value'. Non c'è modo per il preprocessore di dire che non lo sono. – molbdnilo

+1

** static_assert ** è una parola chiave, ** asserire ** una macro del preprocessore. Le macro preprocessore suddividono gli argomenti con ',' in modo non intelligente. Le parentesi aggiuntive impediscono questo. – Youka

risposta

3

È a causa dei token < e >. Scambiano il preprocessore. Ricorda che assert è una macro, non una funzione.

fare questo (aggiungere un ulteriore set di parentesi):

assert((std::is_same<decltype(const_string), decltype(string_const)>::value)); 
    ^                ^
4

Il preprocessore C non riconosce C++ sintassi del modello, quindi staffe modello < e > non sono visti come raggruppamento gettoni dal preprocessore, si' visto come semplici personaggi.

Ciò significa che il preprocessore visualizzare la virgola tra i parametri di modello come separatore di parametri macro, in questo modo:

assert(
    std::is_same<decltype(const_string), 
    decltype(string_const)>::value); 

per forzare il preprocessore per vedere la tua espressione come una singola istruzione, è sufficiente avvolgere il vostro assert parametro una serie supplementare di parentesi:

assert((std::is_same<decltype(const_string), decltype(string_const)>::value)); 

static_assert non ha questa limitazione perché è un C++ keyword, piuttosto che una macro preprocessore come assert() . Ciò significa che supporta pienamente la sintassi C++ e vede i parametri del modello correttamente.