我喜歡頭檔案作為自檔案參考存在。我嘗試將它們保留在帶有檔案注釋的宣告中,然后在我的源檔案中撰寫所有實作。本質上是一個檔案化的介面。
我正在開發一個大量使用模板的專案,而不是用實作細節填充標題(我知道我仍然可以宣告模板并稍后在標題中定義它們,但這并不能解決這個問題)我已經選擇做類似的事情。
// foo.h
template<typename T>
class Foo {
public:
Foo();
T get_foo();
private:
T foo;
}
#include "foo.tpp"
// foo.tpp
template<typename T>
Foo<T>(T f) : foo(f) {};
template<typename T>
T Foo<T>get_foo() { return foo; }
這有一個適度的缺點。任何使用的源代碼都#include "foo.h"必須在 foo 更改時完全重新編譯。從本質上講,這導致我每次更改(概念上但實際上不是)獨立代碼時都需要重新編譯大部分/所有專案。
我明白,由于 C 編譯器處理模板的方式、語言標準或它們的某種組合,當編譯器遇到需要替換的情況時,例如auto f = Foo<int>();,它需要Foo<int>可用的完整定義來正確執行替換。
就沒有辦法解決這個問題嗎?在這種情況下,至少在我看來,foo.tpp作為源檔案,編譯器可以輕松地擴展兩者的模板引數,并將它們編譯為作為獨立 TU 的普通頭檔案/源檔案。然后聯結器只需要稍后找到它們來決議Foo<int>最終鏈接階段的定義。
表面上看,這個例子過于簡單,我遺漏了更復雜的案例和注意事項。我想知道是否有一種實用的方法可以解決這個問題。我正在考慮撰寫一個腳本來為我執行替換,然后編譯這些檔案,但希望有一種已知且更通用的方法。
uj5u.com熱心網友回復:
就沒有辦法解決這個問題嗎?
就在這里。如果在定義函式的翻譯單元中顯式實體化模板,則可以在其他翻譯單元中使用這些實體。
但這當然限制了哪些模板引數可以用于您選擇用于顯式實體化的模板引數。對于不受約束的模板引數,無法在所有翻譯單元(它們被 ODR 使用)中定義函式。
uj5u.com熱心網友回復:
不,除了有兩種不同的方式。
第一種方法是使用特定引數在 cpp 檔案中顯式實體化模板及其方法。然后聯結器會找到這些實作。這需要知道您計劃支持哪些模板引數。
第二個是模塊,沒有編譯器具有工業質量的實作。模塊避免為每個最終用戶重新決議共享模板代碼;仍然需要重新編譯。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/403231.html
標籤:
