2009-11-15 42 views
3

面對在預處理器中是否可以選擇#include s的問題,我立即認爲不可能
..後來才發現它確實可行,你只需要注意參數擴展(例如Boost.Preprocessor可以處理)。宏作爲預處理器指令的參數

儘管如果可能的話,我會避免實際做到這一點,但我想知道爲什麼這會起作用。目前,我未能在C++或C標準中得到有用的理解。
參數化宏是否允許用於任何預處理器指令? (除了#define/#undef
有人可以參考這是允許和總結嗎?

爲好奇利用Boost.Preprocessor爲了簡單

實施例:

#include <boost/preprocessor/cat.hpp> 
#include <boost/preprocessor/stringize.hpp> 

#define INC_LOCAL(a,b) BOOST_PP_STRINGIZE(BOOST_PP_CAT(BOOST_PP_CAT(a,b),.h)) 
#define INC_GLOBAL(a,b) BOOST_PP_CAT(BOOST_PP_CAT(<,a),BOOST_PP_CAT(b,>)) 

#include INC_LOCAL(loc,al) // #include "local.h" 
#include INC_GLOBAL(vect,or) // #include <vector> 

更新: 引用Ç標準,澄清問題。

回答

7

從§16.2-4( 「源文件包含」)的C++ 2003年選秀:

形式的預處理指令

# include pp-tokens new-line 

(不匹配前兩次的一個表格)是允許的。指令中的include之後的預處理標記將按照正常文本(當前定義爲宏名稱的每個標識符都被替換爲預處理標記的列表)處理。

C99的6.10.2-4說的是一樣的。

上面提到的「兩種以前的形式」是# include <h-char-sequence># include "q-char-sequence"。該部分似乎過於簡單,無法總結。

對於其他指令,在任何identifier預處理標記不進行宏擴展(注意不是由語法定義的這種行爲,但通過C++§16/C§6.10):

# if constant-expression new-line [group] 
# ifdef identifier new-line [group] 
# ifndef identifier new-line [group] 
# elif constant-expression new-line [group] 
# else new-line [group] 
# endif new-line 
# include pp-tokens new-line 
# define identifier replacement-list new-line 
# define identifier lparen [identifier-list]) replacement-list new-line 
# undef identifier new-line 
# line pp-tokens new-line 
# error [pp-tokens] new-line 
# pragma [pp-tokens] new-line 
# new-line 

#line是通過C++§16.4-5/C§6.10.4-5進行了明確的宏觀擴展。沒有提到#error(C++§16.5/C§6.10.5)和#pragma(C++§16.6/C§6.10.6)的擴展。 C++§16.3-7/C 6.10。3-8州:

如果#預處理令牌後面跟着一個標識符,在預處理指令可以開始的位置以詞彙形式出現,則標識符不受宏替換的限制。

C++§16.3.1/C§6.10.3.1-1告訴我們,當所述參數給宏函數代入replacement-list,他們是第一宏擴展。類似地,C++第16.3.4節/C第6.10.3.4節中,預處理器宏在替換之後展開replacement-list

總之,宏擴展是針對#if,#elif,#include,#line,宏函數的參數和被替換的宏函數的主體完成的。我認爲這就是一切。

+0

好吧,'pp-tokens'讓我進入'preprocessing-token',從那裏只有'preprocessing-op-or-punc'看起來不錯,但只給一些操作員。 – 2009-11-15 05:50:46

+0

所以'像普通文本一樣處理'意味着像'identifier(identifier,...)'這樣的宏擴展。 – 2009-11-15 06:17:00

+0

當然。結果可能有未定義的行爲。 – outis 2009-11-15 06:31:43

2

這是C預處理器的一個非常基本的功能 - 例如,與這是有可能的宏(如果你必須知道的是,爭論是不允許的參數使用時,一個指令,如#ifdef使得零感除了作爲宏,#ifdef可能的目的是?!)。我不確定ISO C標準的章節和章節會如何幫助你 - 我記得,C++標準不會改變預處理器的操作。

+0

更正:我現在感到困惑其他參數化宏只允許在任何pp-指令,並希望澄清。 – 2009-11-15 05:28:15