强制一个包含文件包含在另一个之前

时间:2015-09-17 13:27:12

标签: c++ conditional-compilation

想象一下,我有两个.hpp个文件:

#ifndef _DEF_FILE_1_
#define _DEF_FILE_1_
inline void some_function_1(){
    /*do stuff*/
}
#endif

#ifndef _DEF_FILE_2_
#define _DEF_FILE_2_
#ifdef _DEF_FILE_1_
inline void some_function_2(){
    /*do stuff using some_function_1()*/
}
#else
inline void some_function_2(){
    /*do the same stuff without using some_function_1()*/
}
#endif
#endif

当我不知道文件的顺序包括在内时,我的问题就出现了,例如: 在main.cpp我可以有类似的东西:

#include "file1.hpp"
#include "file2.hpp"
int main(){
    some_function_2();
    /*will call the function that uses some_function_1()*/
}

#include "file2.hpp"
#include "file1.hpp"
int main(){
    some_function_2();
    /*will call the function that doesn't use some_function_1()*/
}

有没有办法确保file1.hppfile2.hpp 包含在内,然后some_function_2()会调用some_function_1()

PS:一种解决方案是在file1.hpp中加入file2.hpp,但我做不到 因为我开发的代码可能依赖于某些库,也可能不依赖于某些库 最终用户可能有也可能没有。

PPS:我能想到的唯一其他解决方案(即使我不知道如何解决) 实现这一点)将“删除”some_method_2()的定义 包含file1.hpp,然后重新加入file2.hpp

4 个答案:

答案 0 :(得分:1)

我认为正确的解决方案是使用SFINAE机制和模板而不是预处理器技巧重写some_function_2()。那样的实例化将在cpp文件中发生,在那里可以知道some_function_1()是否存在并且include的顺序无关紧要。

答案 1 :(得分:0)

您的用户应该知道他们是否有“某个库”,或者您应该有一些方法来确定该库是否存在。所以你可以这样做:

在file2.hpp

#ifndef _DEF_FILE_2_
#define _DEF_FILE_2_
#ifdef _DEF_HAS_SOME_LIBRARY_
#include "file1.hpp"
inline void some_function_2(){
    /*do stuff using some_function_1()*/
}
#else
inline void some_function_2(){
    /*do the same stuff without using some_function_1()*/
}
#endif
#endif

或者,如果可能的话,完全消除file1.hpp,并将some_function_1()放在上面#include "file1.hpp"的位置。

现在main.cpp应该只包含file2.hpp。

// optionally #define _DEF_HAS_SOME_LIBRARY_
#include "file2.hpp"
int main(){
    some_function_2();
    /*will call the function that uses some_function_1()*/
}
但是,在我看来,避免预处理器的解决方案会更好。

答案 2 :(得分:0)

如果你不知道文件是否存在并且需要处理它,那么c和c ++预处理器都不会处理文件存在检查。这是配置工具背后的原因之一。

您需要事先探测此信息,并在编译之前进行设置。有很多方法可以做到这一点。通常使用工具/脚本创建一些带有适当定义的configure.h标头。例如。包含这样的行#define FILE1_HPP_EXISTS 1

然后,您始终可以依赖configure.h的存在,它将提供您需要的信息。

答案 3 :(得分:0)

如果您的编译器允许,您可以使用_has_include宏:

只需将file2.hpp更改为:

#ifndef _DEF_FILE_2_
#define _DEF_FILE_2_

#if defined(__has_include) && __has_include("file1.hpp")
# include "file1.hpp"
inline void some_function_2() {
    /*do stuff using some_function_1()*/
}
#else
inline void some_function_2() {
    /*do the same stuff without using some_function_1()*/
}
#endif
#endif

但请记住,这是一个特定于编译器的扩展。