توسيع الماكرو قبل Preprocessor إلى توجيه آخر قبل Preprocessor
-
12-09-2019 - |
سؤال
في البداية اعتقدت أنني بحاجة إلى ذلك، لكنني تجنبها في النهاية. ومع ذلك، فإن فضولي (والشهية للمعرفة، همهمة) تجعلني أسأل:
يمكن أن الماكرو قبل preprocessor، على سبيل المثال في
#include "MyClass.h"
INSTANTIATE_FOO_TEMPLATE_CLASS(MyClass)
توسيع إلى أخرى تشمل، كما هو الحال في
#include "MyClass.h"
#include "FooTemplate.h"
template class FooTemplate<MyClass>;
?
المحلول
أعتقد أنه لا يمكن القيام به، وهذا لأن المعالج المسبق هو مسار واحد. وبعد لذلك لا يمكن أن تنبعث منها توجيهات غيرها من التوجيهات.
على وجه التحديد، من معيار C99 (6.10.3.4 الفقرة 3):
3 لا تتم معالجة تسلسل الرمز المميز المسبق تماما مسبقا استبدال الماكرو كإمرين مسبق مسبق التوجيه حتى لو كان يشبه واحد، ...
ومن المثير للاهتمام بما فيه الكفاية، وهذا هو السبب _Pragma
تمت إضافة المشغل إلى C99. لأن #pragma
لا يمكن أن تنبعث من وحدات الماكرو، ولكن _Pragma
يمكن.
نصائح أخرى
يقول قياسي C إن هذا حول توجيهات المعالجة المسبقة (C99 - 6.10 (2) - توجيهات ما قبل البيع):
يتكون التوجيه المعالج مسبق من سلسلة من الرموز المعالجة المسبقة التي تبدأ بممنية مسبقا # (في بداية المرحلة المرحلة 4) ...
و (C99 - 6.10 (7)):
لا تخضع الرموز المعالجة مسبقا لتوجيه مسبق التوجيه إلى توسيع ماكرو ما لم ينص على خلاف ذلك.
مثال في:
#define EMPTY EMPTY # include <file.h>
لا يعد تسلسل الرموز المعالجة المسبقة في السطر الثاني توجيها مسبقا، لأنه لا يبدأ ب # في بداية المرحلة المرحلة 4، على الرغم من أنه ستفعل ذلك بعد استبدال الماكرو فارغ
لذلك، لا، وحدات الماكرو لا يمكن توسيعها في "#include
التوجيه المعالج مسبق. يجب أن تكون هذه التوجيهات في مكانها في بداية المرحلة المرحلة 4 (عند التعامل مع تلك التوجيهات التي تحدث قبل المعالجة مسبقا). منذ حدوث توسع الماكرو خلال المرحلة 4، لا يمكن لحدات الماكرو أن يسبب شيئا ما في بداية المرحلة 4.
أود أن أشير إلى ذلك، أن ما يلي هل الشغل:
#ifdef WIN32
#define PLATFORM_HEADER "platform/windows/platform.h"
#else
#define PLATFORM_HEADER "platform/linux/platform.h"
#include PLATFORM_HEADER
لأن المعيار C يقول هذا (C99، 6.10.2 (4) - إدراج ملف المصدر):
توجيه مسبق من النموذج
# include pp-tokens new-line
(لا يتطابق مع أحد النماذج السابقة). تتم معالجة الرموز المعالجة المسبقة بعد تضمينها في التوجيه كما هو الحال في النص العادي. (يتم استبدال كل معرف محدد حاليا كاسم ماكرو بقائمة استبدال الرموز المعالجة المسبقة.)
يتم تفسير جميع توجيهات مسبقا قبل أن يبدأ توسع الماكرو، لذلك لا، لا يمكنك أن يكون لديك ماكرو يتوسع إلى توجيه #include ويتم تفسيره على هذا النحو. بدلا من ذلك، سيتم تفسيره على أنه (خاطئ) رمز C ++.