Próbuję dowiedzieć się, jakiej wersji Boost mój kod używa. Chcę zrobić coś takiego:
#error BOOST_VERSION
ale preprocesor nie rozwija BOOST_VERSION.
Wiem, że mógłbym wydrukować go w czasie wykonywania z programu i wiem, że mógłbym spojrzeć na dane wyjściowe preprocesora, aby znaleźć odpowiedź. Czuję, że sposób na zrobienie tego podczas kompilacji może być przydatny.
macros
c-preprocessor
boost-preprocessor
Jim Hunziker
źródło
źródło
Odpowiedzi:
Wiem, że minęło dużo czasu od pierwotnego zapytania, ale może to być przydatne.
Można to zrobić w GCC za pomocą operatora stringify „#”, ale wymaga to dwóch etapów.
Wartość makra można następnie wyświetlić za pomocą:
Zobacz: 3.4 Stringifikacja w dokumentacji online gcc.
Jak to działa:
Preprocesor rozumie cytowane ciągi i traktuje je inaczej niż zwykły tekst. Przykładem tego specjalnego traktowania jest konkatenacja ciągów. Komunikat pragma wymaga argumentu będącego łańcuchem cudzysłowu. Jeśli argument zawiera więcej niż jeden składnik, wszystkie muszą być łańcuchami, aby można było zastosować konkatenację ciągów. Preprocesor nigdy nie może założyć, że niecytowany ciąg powinien być traktowany tak, jakby był cytowany. Jeśli tak się stało:
nie będzie się kompilować.
Rozważmy teraz:
co jest równoważne
Powoduje to ostrzeżenie preprocesora, ponieważ abc (bez cudzysłowu) nie może zostać połączone z poprzednim ciągiem.
Rozważmy teraz preprocesor stringize (który kiedyś był nazywany stringification, linki w dokumentacji zostały zmienione, aby odzwierciedlić poprawioną terminologię. (Nawiasem mówiąc, oba terminy są równie obrzydliwe. Prawidłowy termin to oczywiście stringifaction. Przygotuj się do aktualizacji Twoje linki.)). Działa to tylko na argumentach makra i zastępuje nierozwinięty argument argumentem ujęty w podwójne cudzysłowy. A zatem:
przypisze identyczne wartości s1 i s2. Jeśli uruchomisz gcc -E, zobaczysz to na wyjściu. Być może STR byłoby lepiej nazwane czymś w rodzaju ENQUOTE.
To rozwiązuje problem umieszczania cudzysłowów wokół niecytowanego elementu, problem polega teraz na tym, że jeśli argumentem jest makro, makro nie zostanie rozwinięte. Dlatego potrzebne jest drugie makro. XSTR rozszerza swój argument, a następnie wywołuje STR, aby umieścić rozwiniętą wartość w cudzysłowie.
źródło
__IPHONE_9_3
.BOOST_PP_STRINGIZE
wydaje się być doskonałym rozwiązaniem dla C ++, ale nie dla zwykłego C.Oto moje rozwiązanie dla CPP GNU:
Powyższe definicje skutkują:
W przypadku zmiennych „zdefiniowane jako interger” , „zdefiniowane jako łańcuch” i „zdefiniowane, ale bez wartości” , działają one dobrze. Tylko dla zmiennej „niezdefiniowanej” wyświetlały się dokładnie tak samo, jak oryginalna nazwa zmiennej. Trzeba się do tego przyzwyczaić - a może ktoś zaproponuje lepsze rozwiązanie.
źródło
DEFINED_INT=(sizeof(MY_STRUCT))
bez ocenysizeof
operatora.sizeof
, jednak nadal jest ciekawy, czy istnieje sprytny sposób na osiągnięcie tego.)#define masks {0xff, 0xaf, 0x0f}
Jeśli używasz języka Visual C ++, możesz użyć
#pragma message
:Edycja: dzięki LB za link
Najwyraźniej odpowiednik GCC to (nie testowano):
źródło
BOOST_PP_STRINGIZE
która jest ładna i krótka i można ją skopiować / wkleić.O ile wiem, '#error' wypisze tylko ciągi znaków, w rzeczywistości nie musisz nawet używać cudzysłowów .
Czy próbowałeś napisać różne celowo niepoprawne kody przy użyciu „BOOST_VERSION”? Może coś w rodzaju „bla [BOOST_VERSION] = foo;” powie ci coś w rodzaju „literał ciągu 1.2.1 nie może być użyty jako adres tablicy”. Nie będzie to ładny komunikat o błędzie, ale przynajmniej pokaże odpowiednią wartość. Możesz bawić się, aż znajdziesz błąd kompilacji, który mówi ci o wartości.
źródło
std::vector<BOOST_VERSION>;
w gcc 4.4.1. Dzięki!Bez doładowania:
zdefiniuj ponownie to samo makro, a sam kompilator wyświetli ostrzeżenie.
Z ostrzeżenia można zobaczyć lokalizację poprzedniej definicji.
vi o poprzedniej definicji.
źródło
__cplusplus
.W Microsoft C / C ++ możesz użyć wbudowanego
_CRT_STRINGIZE()
do drukowania stałych. Wiele moichstdafx.h
plików zawiera kombinacje następujących elementów:i wyświetla coś takiego:
źródło
Działa, nawet jeśli
preprocess to file
jest włączona, nawet jeśli obecne są nieprawidłowe tokeny:źródło
Build error: #include expects "FILENAME" or <FILENAME>
. Westchnienie.'
:*** WARNING C318 IN LINE 2 OF test.c: can't open file '::*/`'
Możesz również wstępnie przetworzyć plik źródłowy i zobaczyć, do czego szacowana jest wartość preprocesora.
źródło
Czy szukasz
Niedobrze, jeśli BOOST_VERSION jest ciągiem, jak założyłem, ale mogą również istnieć indywidualne liczby całkowite zdefiniowane dla numerów głównych, pomocniczych i numerów wersji.
źródło
#if VARIABLE == 123
instrukcję w locie, a podświetlanie składni mówi mi, czy jest to wartość, którą myślę, czy nie ...Spojrzenie na dane wyjściowe preprocesora jest najbliższe odpowiedzi, o którą prosisz.
Wiem, że wykluczyłeś to (i inne sposoby), ale nie jestem pewien, dlaczego. Masz wystarczająco konkretny problem do rozwiązania, ale nie wyjaśniłeś, dlaczego żadna z „normalnych” metod nie działa dobrze.
źródło
Możesz napisać program, który wydrukuje,
BOOST_VERSION
skompiluje i uruchomi go jako część twojego systemu budowania. W przeciwnym razie myślę, że nie masz szczęścia.źródło
BOOST_VERSION jest zdefiniowana w pliku nagłówka boost version.hpp.
źródło
Zapoznaj się również z dokumentacją Boost, aby dowiedzieć się, jak używasz makra:
W odniesieniu do
BOOST_VERSION
, z 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 :źródło
Zamiast #error spróbuj przedefiniować makro tuż przed jego użyciem. Kompilacja zakończy się niepowodzeniem, a kompilator poda bieżącą wartość, którą według niego ma zastosować do makra.
# zdefiniować BOOST_VERSION bla
źródło