通过宏内联和包含源代码的区别

Difference between inlining and including source through macro

我花了一些时间开发一个 header-only 库,然后偶然发现了一个十字路口。我在网络上到处查看,总是使用内联函数。但是在 stb_image.h 的例子中,源代码只是写在 header 的下半部分,被一个 #ifdef STB_IMAGE_IMPLEMENTATION 包围着,像这样:

#ifndef STB_IMAGE_H_INCLUDED_
#define STB_IMAGE_H_INCLUDED_

void some_func(args);

#endif // STB_IMAGE_H_INCLUDED_

#ifdef STB_IMAGE_IMPLEMENTATION

void some_func(args) {
    // implementation
}

#endif // STB_IMAGE_IMPLEMENTATION;

然后一个(最好不是 main.cpp 的源)文件定义了一个具有相同名称的宏,并在后面包含 header,如下所示:

#include <…>
#include <…>

#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>

// other code

你为什么要用一个而不是另一个? (或者更确切地说,stbi 为什么要这样做?)

STB 是一个 C 库。 C 内联是在 C99 中引入的,不像 C++ 内联那样工作。 C inline 仍然必须只在一个翻译单元中实现。

C++ inline 用于在ODR规则中做例外处理,只要相同就允许多次实现

STB 想成为一个 header 唯一的库,但它们在 C 中并不真正存在,因此他们使用基于宏的解决方案来仅在选定的翻译单元中实现代码。