更多 C++ 惯用法/内联保护宏
使用编译器命令行宏定义开关方便地控制函数的内联性。
为了调试目的,通常需要关闭整个程序中函数的内联。但是对于发布版本,内联函数是可取的。这表明需要一种快速的方法来打开/关闭内联性,具体取决于需要。此外,此类函数应在内联时定义在头文件中,否则应在源代码 (.cpp) 文件中定义。如果非内联函数位于头文件中,则几乎总是会导致函数的多个定义。另一方面,如果内联函数不在头文件中,则编译单元将找不到它们。在这两种情况下,链接器都会抛出错误。
因此,一种灵活的内联方式通常是可取的,但 C++ 语言不支持这种方式,除非使用一些宏技巧。内联保护宏惯用法实现了这一点。
解决方案是将所有内联函数放在一个名为 .ipp 的单独文件中,并用宏 INLINE 装饰每个函数。头文件和实现文件照常创建,.ipp 文件根据是否需要内联,选择性地包含在两个文件(头文件或实现文件)中的一个中。下面给出了一个类 Test 的示例。
// test.ipp file
INLINE void Test::func()
{}
// test.hpp file
#ifndef MYPROJECT_TEST_H // Note include guards.
#define MYPROJECT_TEST_H
class Test
{
public:
void func();
};
#ifdef MYPROJECT_INLINE_ENABLED
#define INLINE inline // Define INLINE as inline (the keyword)
#include "test.ipp" // It is included only when MYPROJECT_INLINE_ENABLED is defined, i.e. inlining is enabled.
#endif
#endif // MYPROJECT_TEST_H
//test.cpp file
#include "test.hpp" // Include header file as usual.
#ifndef MYPROJECT_INLINE_ENABLED
#define INLINE // INLINE is defined as empty string
#include "test.ipp" // It is included only when MYPROJECT_INLINE_ENABLED is NOT defined, i.e. inlining is disabled.
#endif
使用 Include Guard Macro 的效果是,根据 MYPROJECT_INLINE_ENABLED 是否定义,test.ipp 将被 #included 在 test.cpp 或 test.hpp 中。当它与 test.cpp 合并时,函数不会被内联,因为 INLINE 被定义为空字符串。另一方面,当 test.ipp 与 test.hpp 合并时,INLINE 被定义为 inline(关键字)。
现在,剩下的就是根据需要定义 MYPROJECT_INLINE_ENABLED 宏。通常,所有现代 C/C++ 编译器都允许在命令行定义宏。例如,要在 gcc 上使用内联编译上述程序,将参数 -DMYPROJECT_INLINE_ENABLED 选项添加到编译命令行。如果未定义此类宏,则函数将自动被视为非内联,程序可以正常编译。
- ACE(自适应通信环境)
- TAO(ACE ORB)