根據標準,模塊兼容老式頭文件(必須的)……html
若是寫下 import <some_header.h>;
或者 import "some_header.h";
這樣的 import
語句,那麼針對同一個頭文件來講,它們會做爲同一個隱式的獨立模塊來編譯,而且是原子的。緩存
而,如今的預處理器中,#include <some_header.h>
或者 #include "some_header.h"
則是無視任何 C++ 語義,暴力把文件內容複製粘貼進源文件……(逃模塊化
// hello.cpp #include "some_header.h" #include <vector> int main() { std::vector<int> numbers = { 1, 2, 3, 4, 5 }; cao_dan::fuck(numbers); }
針對如上源文件,若是我修改了這裏面的任何內容,都會致使頭文件 <vector>
和 some_header.h
的內容被暴力 #include
進 hello.cpp 而後從新編譯一次。工具
若是頭文件的內容,是一堆模板元的話……這編譯速度,你懂的……(逃ui
// hello.cpp import "some_header.h"; import <vector>; int main() { std::vector<int> numbers = { 1, 2, 3, 4, 5 }; cao_dan::fuck(numbers); }
這種方式,很好地兼容了老式頭文件。不一樣的是,它把同一個頭文件當成一個模塊單元來編譯,並生成 BMI(標準中叫 Binary Module Interface,即二進制模塊接口)文件,緩存起來。這樣在後續編譯中,若是沒改變頭文件 some_header.h
和 <vector>
的內容的話,構建系統就會直接加載這些 BMI,並連接,而不用從新編譯。(666code
問題來了:若是老式頭文件中有宏控制怎麼bang?htm
// legacy.h #pragma once #ifdef SOME_OPTION_1 // ... #elif defined(SOME_OPTION_2) //... #endif
針對以上頭文件,採用 import "legacy.h"
的方式沒法導入宏,也就沒法讓用戶設置生效。這種狀況,大佬們也考慮到了。推薦的作法是用包裝頭文件實現。接口
// legacy_some_option_1.h #pragma once #define SOME_OPTION_1 #include <legacy.h>
// legacy_some_option_2.h #pragma once #define SOME_OPTION_2 #include <legacy.h>
這樣 legacy_some_option_1.h
就是針對 SOME_OPTION_1
的設置, legacy_some_option_2.h
就是針對 SOME_OPTION_2
的設置。get
使用以下:編譯器
// main.cpp import "legacy_some_option_1.h"; // import "legacy_some_option_2.h"; // ...
針對這個 BMI 以及其派生出來的 C++ 生態系統技術報告,準備在 C++ 20 發佈以前擬定。主要包括一些亟待統一的地方:
boost.asio
怎麼對應到具體的 BMI 文件或源文件,這個規則是什麼?)