Domanda

Sto cercando di capire quale versione di Boost mio codice pensa che sta utilizzando. Voglio fare qualcosa di simile:

#error BOOST_VERSION

, ma il preprocessore non si espande BOOST_VERSION.

So che potrei stamparlo a tempo di esecuzione del programma, e so che potrei guardare l'output del preprocessore per trovare la risposta. Mi sento come avere un modo di fare questo durante la compilazione potrebbe essere utile.

È stato utile?

Soluzione

Se si utilizza Visual C ++, è possibile utilizzare #pragma message:

#include <boost/preprocessor/stringize.hpp>
#pragma message("BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION))

Modifica Grazie a LB di collegamento

A quanto pare, il GCC è equivalente (non testato):

#pragma message "BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION)

Altri suggerimenti

BOOST_PP_STRINGIZE sembra un ottima soluzione per C ++, ma non per regolare C.

Ecco la mia soluzione per GNU CPP:

/* Some test definition here */
#define DEFINED_BUT_NO_VALUE
#define DEFINED_INT 3
#define DEFINED_STR "ABC"

/* definition to expand macro then apply to pragma message */
#define VALUE_TO_STRING(x) #x
#define VALUE(x) VALUE_TO_STRING(x)
#define VAR_NAME_VALUE(var) #var "="  VALUE(var)

/* Some example here */
#pragma message(VAR_NAME_VALUE(NOT_DEFINED))
#pragma message(VAR_NAME_VALUE(DEFINED_BUT_NO_VALUE))
#pragma message(VAR_NAME_VALUE(DEFINED_INT))
#pragma message(VAR_NAME_VALUE(DEFINED_STR))

Sopra le definizioni si traducono in:

test.c:10:9: note: #pragma message: NOT_DEFINED=NOT_DEFINED
test.c:11:9: note: #pragma message: DEFINED_BUT_NO_VALUE=
test.c:12:9: note: #pragma message: DEFINED_INT=3
test.c:13:9: note: #pragma message: DEFINED_STR="ABC"

"definito come interger" , "definito come stringa" e "definito ma nessun valore" le variabili, funzionano bene . Solo per "non definito" variabile, che appare esattamente uguale al nome variabile originale. Bisogna abituarsi ad esso -. O forse qualcuno in grado di fornire una soluzione migliore

So che questo è un molto tempo dopo la query originale, ma questo può ancora essere utile.

Questo può essere fatto in GCC utilizzando l'operatore stringa i "#", ma richiede due fasi.

#define XSTR(x) STR(x)
#define STR(x) #x

Il valore di una macro può essere visualizzato con:

#pragma message "The value of ABC: " XSTR(ABC)

Si veda:. 3.4 Forzare a stringa nella documentazione in linea gcc

Come funziona:

Il preprocessore capisce stringhe tra virgolette e li gestisce in modo diverso da testo normale. Stringa concatenazione è un esempio di tale trattamento specifico. Il pragma messaggio richiede un argomento che è una stringa tra virgolette. Quando v'è più di un componente per l'argomento allora devono essere tutti corde in modo che la concatenazione di stringhe può essere applicata. Il preprocessore non può mai assumere che una stringa non quotate dovrebbe essere trattato come se fosse citato. Se così fosse, allora:

#define ABC 123
int n = ABC;

non sarebbe la compilazione.

Consideriamo ora:

#define ABC abc
#pragma message "The value of ABC is: " ABC

che è equivalente a

#pragma message "The value of ABC is: " abc

Questo fa sì che un avvertimento preprocessore perché abc (non quotate) non può essere concatenato con la stringa precedente.

Consideriamo ora lo stringize preprocessore (che un tempo si chiamava in stringa, i collegamenti nella documentazione sono stati modificati in modo da riflettere la terminologia riveduta. (Entrambi i termini, per inciso, sono ugualmente detestabili. Il termine corretto è, naturalmente, stringifaction. Be pronto ad aggiornare i link.)) dell'operatore. Questo agisce solo sugli argomenti di una macro e sostituisce l'argomento non espanso con l'argomento racchiusa tra doppi apici. Così:

#define STR(x) #x
char *s1 = "abc";
char *s2 = STR(abc);

assegna valori identici a s1 e s2. Se si esegue gcc -E si può vedere questo in uscita. Forse sarebbe meglio STR chiamato qualcosa come ENQUOTE.

Questo risolve il problema di mettere le virgolette attorno a un oggetto non quotate, il problema ora è che, se l'argomento è una macro, la macro non verrà ampliato. Questo è il motivo per cui è necessaria la seconda macro. XSTR espande il suo argomento, quindi chiama STR per mettere il valore espanso tra virgolette.

Per quanto ne so '#error' solo stamperà le stringhe, infatti don 't nemmeno bisogno di usare le virgolette .

Hai provato a scrivere varie Codice volutamente errato utilizzo di "BOOST_VERSION"? Forse qualcosa di simile a "blah [BOOST_VERSION] = foo;" vi dirà qualcosa come "stringa 1.2.1 letterale non può essere utilizzato come un indirizzo di matrice". Non sarà un messaggio di errore abbastanza, ma almeno ti mostrerà il relativo valore. Si può giocare fino a individuare un errore di compilazione che ti dice il valore.

Senza spinta:

  1. definire come prima macro e compilatore stesso vi darà avvertimento.

  2. Da avvertimento è possibile vedere posizione del precedente definizione.

  3. file VI della precedente definizione.

ambarish@axiom:~/cpp$ g++ shiftOper.cpp
shiftOper.cpp:7:1: warning: "LINUX_VERSION_CODE" redefined
shiftOper.cpp:6:1: warning: this is the location of the previous definition

#define LINUX_VERSION_CODE 265216
#define LINUX_VERSION_CODE 666

int main ()
{

}
#define a <::BOOST_VERSION>
#include a
MSVC2015 : Errore irreversibile C1083: Impossibile aprire il file di inclusione: ':: 106200': No such file or directory

Funziona anche se preprocess to file è abilitato, anche se i token non validi sono presenti:

#define a <::'*/`#>
#include a
MSVC2015 : l'errore irreversibile C1083: Impossibile aprire il file di inclusione: '::' * / '#': No such file or directory
GCC4.x : avvertimento: manca di terminazione 'carattere [-Winvalid-pp-token]
    #define un <:: '* / `#>

In Microsoft C / C ++, è possibile utilizzare le costanti incorporate _CRT_STRINGIZE() per la stampa. Molti dei miei file stdafx.h contengono una combinazione di queste:

#pragma message("_MSC_VER      is " _CRT_STRINGIZE(_MSC_VER))
#pragma message("_MFC_VER      is " _CRT_STRINGIZE(_MFC_VER))
#pragma message("_ATL_VER      is " _CRT_STRINGIZE(_ATL_VER))
#pragma message("WINVER        is " _CRT_STRINGIZE(WINVER))
#pragma message("_WIN32_WINNT  is " _CRT_STRINGIZE(_WIN32_WINNT))
#pragma message("_WIN32_IE     is " _CRT_STRINGIZE(_WIN32_IE))
#pragma message("NTDDI_VERSION is " _CRT_STRINGIZE(NTDDI_VERSION)) 

ed emette qualcosa di simile:

_MSC_VER      is 1915
_MFC_VER      is 0x0E00
_ATL_VER      is 0x0E00
WINVER        is 0x0600
_WIN32_WINNT  is 0x0600
_WIN32_IE     is 0x0700
NTDDI_VERSION is 0x06000000

Si potrebbe anche pre-elaborare i file di origine e vedere che cosa il valore preprocessore restituisce.

Sei alla ricerca di

#if BOOST_VERSION != "1.2"
#error "Bad version"
#endif

Non è fantastico se BOOST_VERSION è una stringa, come ho pensato, ma ci possono essere anche singoli interi definiti per i maggiori, minori e revisione numeri.

Guardando l'output del preprocessore è la cosa più vicina alla risposta che chiedete.

So che hai escluso che (e altri modi), ma io non so perché. Avete un problema abbastanza specifico da risolvere, ma non è stato spiegato il motivo per cui uno dei metodi di "normali" non funzionano bene per voi.

Si potrebbe scrivere un programma che stampi BOOST_VERSION e compilare ed eseguire come parte del vostro sistema di compilazione. In caso contrario, penso che tu sei fuori di fortuna.

BOOST_VERSION è definita nel file di intestazione spinta version.hpp.

Date un'occhiata alla documentazione Boost, nonché, per quanto riguarda come si utilizza la macro:

Con riferimento alle BOOST_VERSION, da http://www.boost.org/doc/libs/1_37_0/libs/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.boost_helper_macros :

  

Descrive il numero di versione spinta in   formato XXYYZZ tale che:    (BOOST_VERSION % 100) è il sub-minor   versione, ((BOOST_VERSION / 100) %    1000) è la versione minore, e    (BOOST_VERSION / 100000) è il principale   versione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top