سؤال

أحاول معرفة إصدار تعزيز الكود الخاص بي يعتقد أنه يستخدم. أريد أن أفعل شيئًا كهذا:

#error BOOST_VERSION

لكن المعالج المسبق لا يوسع BOOST_VERSION.

أعلم أنه يمكنني طباعته في وقت التشغيل من البرنامج ، وأنا أعلم أنه يمكنني النظر في إخراج المعالج المسبق للعثور على الإجابة. أشعر أن لدي طريقة للقيام بذلك أثناء التجميع يمكن أن يكون مفيدًا.

هل كانت مفيدة؟

المحلول

إذا كنت تستخدم Visual C ++ ، فيمكنك الاستخدام #pragma message:

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

تعديل: بفضل LB للرابط

على ما يبدو ، ما يعادل GCC هو (لم يتم اختباره):

#pragma message "BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION)

نصائح أخرى

BOOST_PP_STRINGIZE يبدو حلاً ممتازًا لـ C ++ ، ولكن ليس لـ C. العادية

هذا هو الحل الخاص بي لـ 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))

التعريفات أعلاه تؤدي إلى:

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"

ل "تعريف interger", "تعريف كسلسلة", ، و "محددة ولكن لا قيمة" المتغيرات ، أنها تعمل على ما يرام. فقط ل "غير معرف" متغير ، عرضت بالضبط نفس الاسم المتغير الأصلي. يجب أن تستخدم في ذلك - أو ربما يمكن لشخص ما توفير حل أفضل.

أعلم أن هذا هو وقت طويل بعد الاستعلام الأصلي ، ولكن قد لا يزال هذا مفيدًا.

يمكن القيام بذلك في مجلس التعاون الخليجي باستخدام مشغل stringify "#" ، لكنه يتطلب مرحلتين.

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

يمكن بعد ذلك عرض قيمة الماكرو مع:

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

راجع: 3.4 سلسلة في وثائق GCC عبر الإنترنت.

كيف تعمل:

يفهم المعالج المسبق الأوتار المقتبسة ويتعامل معها بشكل مختلف عن النص الطبيعي. سلسلة سلسلة هو مثال على هذا العلاج الخاص. تتطلب الرسالة pragma وسيطة هي سلسلة مقتبسة. عندما يكون هناك أكثر من مكون واحد إلى الوسيطة ، يجب أن تكون جميعها سلاسل بحيث يمكن تطبيق تسلسل السلسلة. لا يمكن للمعالج المسبق أن يفترض أبدًا أنه ينبغي التعامل مع سلسلة غير مؤهلة كما لو كانت مقتبسة. إذا حدث ذلك:

#define ABC 123
int n = ABC;

لن يجمع.

الآن ضع في اعتبارك:

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

وهو ما يعادل

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

هذا يسبب تحذيرًا قبل المعالج لأنه لا يمكن تسلسل ABC (غير مؤهل) مع السلسلة السابقة.

الآن ضع في اعتبارك المعالج المسبق (الذي كان يسمى ذات مرة الخيط ، تم تغيير الروابط الواردة في الوثائق لتعكس المصطلحات المنقحة. (كلا المصطلحين ، بالمناسبة ، يمكن التخلص منهما على قدم المساواة. المصطلح الصحيح ، بالطبع ، stringifaction. روابطك.)) المشغل. هذا لا يعمل إلا على حجج الماكرو ويحل محل الحجة غير المألوفة مع الوسيطة المرفقة في اقتباسات مزدوجة. هكذا:

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

سيقوم بتعيين قيم متطابقة إلى S1 و S2. إذا قمت بتشغيل GCC -e يمكنك رؤية هذا في الإخراج. ربما سيكون ستر أفضل اسم شيء مثل Enquote.

هذا يحل مشكلة وضع عروض أسعار حول عنصر غير مؤهل ، المشكلة الآن هي أنه إذا كانت الوسيطة ماكرو ، فلن يتم توسيع الماكرو. هذا هو السبب في حاجة إلى الماكرو الثاني. تقوم XSTR بتوسيع حجتها ، ثم تستدعي STR لوضع القيمة الموسعة في عروض أسعار.

بقدر ما أعرف "#error" فقط سوف يطبع السلاسل ، في الواقع لا تحتاج حتى إلى استخدام عروض الأسعار.

هل حاولت كتابة كود غير صحيح عن قصد باستخدام "boost_version"؟ ربما شيء مثل "بلاه [boost_version] = foo ؛" سوف أخبرك بشيء مثل "String Literal 1.2.1 لا يمكن استخدامه كعنوان صفيف". لن تكون رسالة خطأ جميلة ، لكنها على الأقل ستظهر لك القيمة ذات الصلة. يمكنك اللعب حتى تجد خطأ ترجمة يخبرك بالقيمة.

بدون تعزيز:

  1. حدد نفس الماكرو مرة أخرى وسيقوم برنامج التحويل البرمجي نفسه بتحذير.

  2. من التحذير يمكنك رؤية موقع التعريف السابق.

  3. ملف السادس من التعريف السابق.

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: خطأ فادح C1083: لا يمكن فتح ملف الملف: ':: 106200': لا يوجد مثل هذا الملف أو الدليل

يعمل حتى لو preprocess to file تم تمكينه ، حتى لو كانت الرموز غير صالحة موجودة:

#define a <::'*/`#>
#include a
MSVC2015: خطأ فادح C1083: لا يمكن فتح ملف الملف: '::'*/`#': لا يوجد مثل هذا الملف أو الدليل
GCC4.x: تحذير: مفقود الطرف "---winvalid-ppp-token
#Define A <:: '*/`#>

في Microsoft C/C ++ ، يمكنك استخدام المدمج في _CRT_STRINGIZE() لطباعة الثوابت. كثير من بلدي stdafx.h تحتوي الملفات على مزيج من هذه:

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

ويخرج شيئًا كهذا:

_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

يمكنك أيضًا المعالجة المسبقة للملف المصدر ومعرفة قيمة المعالج المسبق لتقييمها.

هل تبحث عن

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

ليس رائعًا إذا كانت Boost_version عبارة عن سلسلة ، كما افترضت ، ولكن قد يكون هناك أيضًا أعداد صحيحة فردية محددة للأرقام الرئيسية والثانوية والمراجعة.

إن النظر إلى إخراج المعالج المسبق هو أقرب شيء إلى الإجابة التي تطلبها.

أعلم أنك استبعدت ذلك (وطرق أخرى) ، لكنني لست متأكدًا من السبب. لديك مشكلة محددة بما يكفي لحلها ، لكنك لم تشرح لماذا لا تعمل أي من الأساليب "العادية" بشكل جيد بالنسبة لك.

يمكنك كتابة برنامج يطبع BOOST_VERSION وتجميعه وتشغيله كجزء من نظام البناء الخاص بك. خلاف ذلك ، أعتقد أنك محظوظ.

يتم تعريف BOOST_VERVENT في إصدار ملف BOOST HEADER.

ألقِ نظرة على وثائق Boost أيضًا ، فيما يتعلق بكيفية استخدامك للماكرو:

بالنسبة إلى BOOST_VERSION, ، من عند 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:

يصف رقم إصدار Boost بتنسيق xxyyzz بحيث: (BOOST_VERSION % 100) هو نسخة الأقراص الفرعية ، ((BOOST_VERSION / 100) % 1000) هي النسخة الثانوية ، و (BOOST_VERSION / 100000) هو النسخة الرئيسية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top