Ric*_*ges 12 c++ macros include boost-preprocessor
我想为宏程序动态创建的包含文件路径,用于程序的目标配置相关部分.
例如,我想构建一个可以像这样调用的宏:
#include TARGET_PATH_OF(header.h)
Run Code Online (Sandbox Code Playgroud)
这会扩展到这样的事情:
#include "corefoundation/header.h"
Run Code Online (Sandbox Code Playgroud)
当为OSX配置源(在本例中)时
到目前为止,所有尝试都失败了 我希望以前有人这样做过吗?
什么不起作用的例子:
#include <iostream>
#include <boost/preprocessor.hpp>
#define Dir directory/
#define File filename.h
#define MakePath(f) BOOST_PP_STRINGIZE(BOOST_PP_CAT(Dir,f))
#define MyPath MakePath(File)
using namespace std;
int main() {
// this is a test - yes I know I could just concatenate strings here
// but that is not the case for #include
cout << MyPath << endl;
}
Run Code Online (Sandbox Code Playgroud)
错误:
./enableif.cpp:31:13: error: pasting formed '/filename', an invalid preprocessing token
cout << MyPath << endl;
^
./enableif.cpp:26:16: note: expanded from macro 'MyPath'
#define MyPath MakePath(File)
^
./enableif.cpp:25:40: note: expanded from macro 'MakePath'
#define MakePath(f) BOOST_PP_STRINGIZE(BOOST_PP_CAT(Dir,f))
^
/usr/local/include/boost/preprocessor/cat.hpp:22:32: note: expanded from macro 'BOOST_PP_CAT'
# define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
^
/usr/local/include/boost/preprocessor/cat.hpp:29:36: note: expanded from macro 'BOOST_PP_CAT_I'
# define BOOST_PP_CAT_I(a, b) a ## b
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
ric*_*ici 14
我倾向于同意utnapistim的答案中的评论,即使你可以,你也不应该这样做.但实际上,您可以使用符合标准的C编译器.[注1]
有两个问题需要克服.第一个是你不能使用##
运算符来创建一个不是有效的预处理器标记的东西,并且路径名不符合有效的预处理器标记,因为它们包含/和.字符.(.如果令牌以数字开头,那/就没问题,但是永远不会有效.)
实际上,您不需要连接标记以便将它们与#
运算符进行字符串化,因为该运算符将对整个宏参数进行字符串化,并且参数可能包含多个标记.但是,stringify尊重空格[注2],所以STRINGIFY(Dir File)
不起作用; 它会导致"directory/ filename.h"
文件名中的无关空间导致#include
失败.所以你需要连接Dir
并且File
没有任何空格.
下面通过使用类似函数的宏来解决第二个问题,它只返回它的参数:
#define IDENT(x) x
#define XSTR(x) #x
#define STR(x) XSTR(x)
#define PATH(x,y) STR(IDENT(x)IDENT(y))
#define Dir sys/
#define File socket.h
#include PATH(Dir,File)
Run Code Online (Sandbox Code Playgroud)
请注意,Dir
将保留调用中的空白字符.所以File
会失败.
当然,unix
如果你可以编写没有空格的连接,你就不需要宏的复杂性.例如:
#define XSTR(x) #x
#define STR(x) XSTR(x)
#define Dir sys
#define File socket.h
#include STR(Dir/File)
Run Code Online (Sandbox Code Playgroud)
我用godbolt上的clang,gcc和icc尝试过它.我不知道它是否适用于Visual Studio.
更准确地说,它半空间:空白空间被转换为单个空格字符.