Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在宏中生成包含文件名_C++_Macros_Include - Fatal编程技术网

C++ 在宏中生成包含文件名

C++ 在宏中生成包含文件名,c++,macros,include,C++,Macros,Include,我试图在宏中生成包含文件名。这在C++中应该是合法的: #define INCLUDE_FILE "module_impl_win.hpp" #include INCLUDE_FILE 这很好,但一旦我尝试生成文件名,它就无法编译 #define INCLUDE_FILE(M) M##"_impl_win.hpp" #include INCLUDE_FILE("module") 实际上,它在MSVC2010上给了我警告 警告C4067:预处理器指令后出现意外标记-应为newlin 但它不包括

我试图在宏中生成包含文件名。这在C++中应该是合法的:

#define INCLUDE_FILE "module_impl_win.hpp"
#include INCLUDE_FILE
这很好,但一旦我尝试生成文件名,它就无法编译

#define INCLUDE_FILE(M) M##"_impl_win.hpp"
#include INCLUDE_FILE("module")
实际上,它在MSVC2010上给了我警告

警告C4067:预处理器指令后出现意外标记-应为newlin

但它不包括文件


有什么问题?我怎样才能摆脱它?

问题是,最终您的代码会是这样的:

#include "module""_impl_win.hpp"
这会产生与您所看到的相同的警告和错误,但会以稍微更明显的方式产生

虽然编译器将接受该语法,但预处理器不会接受


我没有一个建议来说明你想做什么工作。我个人不想使用这种类型的宏,因为它使代码的视觉导航更加困难,并且可能会阻止许多编辑器快速导航代码。

我会使用辅助引用宏来完成这一操作。这样的东西会给你想要的:

#define QUOTEME(M)       #M
#define INCLUDE_FILE(M)  QUOTEME(M##_impl_win.hpp)

#include INCLUDE_FILE(module)

您还可以使用Boost预处理器,尤其是/宏:

#包括
#包括
#定义INCLUDE_FILE(M)BOOST_PP_STRINGIZE(BOOST_PP_CAT(M,_impl_win.hpp))
//扩展为:#包括“module_impl_win.hpp”
#包含文件(模块)
(参见)


请注意,这与@Andrew的答案(前导下划线=保留标识符)存在相同的问题。

谢谢,我不知道它是这样连接字符串的。假设有数百个文件包含带有#ifdef#恩迪夫。如果明天我将添加对一个以上平台的支持,那么我将需要编辑所有这些文件,而不仅仅是编辑一个宏和添加特定于平台的实现文件。“这太可悲了。@ledokol:为什么平台特定的功能不能被分割成单独的头文件和源文件,而不包括在其他地方?”?将特定于平台和依赖于平台的功能整合到一组相对较小的文件中应该很容易。您的意思是为什么不使用PIMPL来分离特定于平台的代码?嗯,它不能到处都用。有许多模板类需要特定于平台的实现类声明。因此,我必须将其拆分为头文件和实现文件。举个例子。我们有一个线程模板类,它使用thread\u impl实现类。thread_impl是为windows和unix实现的,因此有thread_impl_win和thread_impl_nix头文件。线程头文件必须包含其中一个才能使用thread_impl类。使用这种方法时必须小心
\u impl\u win
是一个标识符标记,由于它以下划线开头(在宏名称空间中),因此它保留给实现。您应该将前导的
\uuu
断开,并将其单独连接起来,尽管我不知道如何在这里这样做,因为
\uu
本身是一个保留标识符。@James McNellis:Standard只保留带有下划线和大写字符的名称(或包含双下划线的名称)。我不知道为什么Sutter建议避免在任何地方使用下划线。@ledokol:任何以下划线开头的名称都保留在全局名称空间中(宏名称空间是一种“全局”名称空间)。至于可移植性,一般来说,这种方法应该是可移植的,尽管在include指令中宏的扩展是如何指定的有一些特殊性。@詹姆斯·麦克内利斯:刚刚检查了标准。是的,对不起。您是对的(每个以下划线开头的名称都保留给实现,以用作全局命名空间中的名称)。也许最好包含“module”并将其与impl#u win.hpp连接起来。首先,像
QUOTEME(M##.hpp)
QUOTEME(M##/impl.hpp)
这样的东西不起作用。
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>

#define INCLUDE_FILE(M) BOOST_PP_STRINGIZE(BOOST_PP_CAT(M, _impl_win.hpp))

// expands to: #include "module_impl_win.hpp"
#include INCLUDE_FILE(module)