2012-11-21 11 views
5

Vorrei produrre una stringa statica della forma "example.cpp:34" con il preprocessore, ma la macro __FILE__ si espanderà per "lib/example/example.cpp" e __LINE__ espande a 34 come intero. Posso costruire la stringa desiderata con il preprocessore? Le estensioni del GCC sono ok.Cpp preprocessore e nome base del nome, il numero di riga come stringa

Modifica La parte più importante è che io voglio una stringa C-statica stile, quindi non è possibile utilizzare la funzione basename. Mi chiedo se c'è qualche modo nel preprocessore per replicare quella funzionalità, possibilmente con un'estensione boost?

+0

è C++ 11 ok? La stringa deve essere utilizzabile nel preprocessore o solo in fase di compilazione? – kennytm

+0

@KennyTM No, non posso usare C++ 11. Lo voglio al momento della compilazione. Anche la spinta va bene. –

+0

O non utilizzare '__FILE__', ma definire il proprio valore letterale di stringa sopra ogni file di interesse. – chill

risposta

0

Dovreste essere in grado di utilizzare solo basename() come __FILE__ espande ad un const C stringa

__FILE__ Questa macro restituisce il nome del file corrente, sotto forma di una stringa C costante .

printf ("%s:%d\n", basename(__FILE__), __LINE__); 
+0

Voglio una c-string statica, quindi non può essere l'output di una funzione. –

+0

@pythonicmetaphor cosa intendi con il risultato di una funzione? vuoi restituirlo da una funzione? – iabdalkader

+0

Voglio dire che voglio una stringa statica, quindi non posso usare nessuna funzione, solo il preprocessore per costruirla. –

2

Si può approfittare del fatto che adiacenti stringhe letterali sono concatenati:

#define STRINGIFY(s) #s 
#define FILELINE(line) __FILE__ ":" str(line) 

quindi utilizzarlo come FILELINE(__LINE__). Non lo faccio molto spesso, quindi potrebbe esserci un modo migliore di dover passare la macro __LINE__. Funziona per me comunque, il test con:

#include <iostream> 

#define str(s) #s 
#define FILELINE(line) __FILE__ ":" str(line) 

int main(int argc, const char* argv[]) 
{ 
    std::cout << FILELINE(__LINE__) << std::endl; 
    return 0; 
} 

ottengo:

main.cpp:9 
+0

Certo, quindi immagino che il problema sia davvero il basename. Ottieni main.cpp perché non includi un file in una directory diversa. –

0

Non so di un modo per ottenere il nome di base, ma oyther quello che si può utilizzare l'operatore in stringa preprocessore '#', come:

#define M__(x,y) x ":" #y 
#define M_(x,y) M__(x, y) 
#define M M_(__FILE__, __LINE__) 

Ora M si espanderà per "lib/example/example.cpp:34" (dato lo metti in quel file su quella linea, OFC :))

0

Bene, non deve essere utilizzato solo il preprocessore, ma non verrà visualizzato all'utente finale.

Quando si desidera BASENAME() da utilizzare in qualche file - usano questo file di intestazione basename.h:

// basename.h 
#include <string.h> 

static size_t basename_start_calc(const char* filename) 
{ 
    const char* base = strrchr(filename, '/'); 
    return base ? (base - filename + 1) : 0; 
} 
static inline size_t basename_start(const char* filename) 
{ 
    static size_t retval = basename_start_calc(filename); 
    return retval; 
} 
#define STR_(t) #t 
#define STR(t) STR_(t) 
#define BASENAME() ((__FILE__ ":" STR(__LINE__)) + basename_start(__FILE__)) 

An ideone example here.

basename_start(__FILE__) verrà valutato solo una volta per il file sorgente specificato. Purtroppo non è possibile utilizzare questa soluzione nei file di intestazione, solo nei file di origine. Puoi cambiarlo, quindi può essere usato ovunque, ma l'inizio della baseline per il nome file specificato verrà calcolato ogni volta. Basta usare in BASENAME()basename_start_calc(__FILE__) invece di basename_start(__FILE__) ...

Credo che questo è meglio che si può avere automaticamente.

Naturalmente è possibile definire manualmente in ogni file di macro:

#define BASENAME() ("somefile.cpp:" STR(__LINE__)) 

ma non sono sicuro che questo è quello che si voleva ....

Problemi correlati