Pergunta

Estou tentando descobrir qual versão do Boost meu código pensa que está usando. Eu quero fazer algo assim:

#error BOOST_VERSION

Mas o pré -processador não expande o boost_version.

Sei que poderia imprimi-lo em tempo de execução do programa e sei que poderia olhar para a saída do pré-processador para encontrar a resposta. Eu sinto que ter uma maneira de fazer isso durante a compilação pode ser útil.

Foi útil?

Solução

Se você estiver usando o Visual C ++, pode usar #pragma message:

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

Editar: Obrigado a LB pelo link

Aparentemente, o equivalente do GCC é (não testado):

#pragma message "BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION)

Outras dicas

BOOST_PP_STRINGIZE Parece uma excelente solução para C ++, mas não para C. regular

Aqui está minha solução para 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))

As definições acima resultam em:

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"

Por "definido como interger", "definido como string", e "Definido, mas sem valor" Variáveis, elas funcionam muito bem. Apenas para "não definido" Variável, eles exibiram exatamente o mesmo que o nome da variável original. Você tem que ser usado - ou talvez alguém possa fornecer uma solução melhor.

Eu sei que isso é muito tempo após a consulta original, mas isso ainda pode ser útil.

Isso pode ser feito no GCC usando o operador Stringify "#", mas requer dois estágios.

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

O valor de uma macro pode ser exibido com:

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

Veja: 3.4 Stringification na documentação online do GCC.

Como funciona:

O pré -processador entende as cordas citadas e as lida de maneira diferente do texto normal. A concatenação de string é um exemplo deste tratamento especial. A mensagem Pragma requer um argumento que seja uma string citada. Quando há mais de um componente no argumento, todos devem ser strings para que a concatenação da string possa ser aplicada. O pré -processador nunca pode assumir que uma sequência não cotada deve ser tratada como se fosse citada. Se isso aconteceu então:

#define ABC 123
int n = ABC;

não compilaria.

Agora considere:

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

que é equivalente a

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

Isso causa um aviso pré -processador porque o ABC (não cotado) não pode ser concatenado com a sequência anterior.

Agora, considere o pré -processador Stringize (que já foi chamado de Stringification, os links na documentação foram alterados para refletir a terminologia revisada (ambos os termos, incidentalmente, são igualmente detestáveis. O termo correto está, é claro, Stringifaction. Esteja pronto para atualizar seus links.)) Operador. Isso atua apenas nos argumentos de uma macro e substitui o argumento não exposto pelo argumento incluído em cotações duplas. Desta forma:

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

atribuirá valores idênticos a S1 e S2. Se você executar GCC -e, poderá ver isso na saída. Talvez STR fosse melhor chamado algo como Enquote.

Isso resolve o problema de colocar citações em torno de um item não cotado, o problema agora é que, se o argumento for uma macro, a macro não será expandida. É por isso que a segunda macro é necessária. O XSTR expande seu argumento e chama o STR para colocar o valor expandido em cotações.

Tanto quanto eu sei, '#Error' apenas imprimirá cordas, de fato Você nem precisa usar aspas.

Você já tentou escrever vários código propositadamente incorretos usando "boost_version"? Talvez algo como "blá [boost_version] = foo;" dirá a você algo como "String literal 1.2.1 não pode ser usado como um endereço de matriz". Não será uma mensagem de erro bonita, mas pelo menos mostrará o valor relevante. Você pode brincar até encontrar um erro de compilação que informe o valor.

Sem aumento:

  1. Defina a mesma macro novamente e o próprio compilador dará aviso.

  2. A partir do aviso, você pode ver a localização da definição anterior.

  3. VI Arquivo da definição anterior.

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: Erro fatal C1083: Não é possível abrir o arquivo: ':: 106200': nenhum arquivo ou diretório

Funciona mesmo se preprocess to file está ativado, mesmo que tokens inválidos estejam presentes:

#define a <::'*/`#>
#include a
MSVC2015: Erro fatal C1083: Não é possível abrir o arquivo: '::'*/`#': nenhum arquivo ou diretório
Gcc4.x: Aviso: Periando que o personagem '[-WinValid-pp-token
#Define a <:: '*/`#>

Na Microsoft C/C ++, você pode usar o embutido _CRT_STRINGIZE() para imprimir constantes. Muitos dos meus stdafx.h Os arquivos contêm alguma combinação destes:

#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)) 

e produz algo assim:

_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

Você também pode pré -processar o arquivo de origem e ver a que o valor pré -processador avalia.

Você está procurando

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

Não é ótimo se o Boost_version for uma string, como eu assumi, mas também pode haver números inteiros individuais definidos para os números principais, menores e de revisão.

Olhar para a saída do pré -processador é a coisa mais próxima da resposta que você solicita.

Eu sei que você excluiu isso (e outras maneiras), mas não sei por quê. Você tem um problema específico o suficiente para resolver, mas não explicou por que nenhum dos métodos "normais" não funciona bem para você.

Você pode escrever um programa que imprime BOOST_VERSION e compilar e executá -lo como parte do seu sistema de construção. Caso contrário, acho que você está sem sorte.

Boost_version é definido na versão do arquivo de cabeçalho do Boost.hpp.

Dê uma olhada na documentação do Boost também, sobre como você está usando a macro:

Em referência a BOOST_VERSION, a partir de 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:

Descreve o número da versão Boost em formato xxyyzz de tal forma que: (BOOST_VERSION % 100) é a versão sub-minor, ((BOOST_VERSION / 100) % 1000) é a versão menor, e (BOOST_VERSION / 100000) é a versão principal.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top