一:概述
????????模板在 C++ 中是編譯期展開的,不同模板參數會生成不同的代碼,這使得模板類/函數天然不具備 ABI 穩定性。為了保持ABI穩定,接口不要直接用模板,先用普通類打個底,模板只是“外殼”,這樣 ABI 才穩定。這樣做有兩個好處:
-
所有模板實例共享一個實現代碼(避免為每個
List<T>
生成一份幾乎相同的add_front
、unlink
等函數)。 -
核心邏輯只定義一次,因此更容易保持 ABI 穩定性,并且編譯速度更快。
二:示例
???????Link_base
是一個通用的雙向鏈表節點結構,不帶類型信息,List_base
是核心鏈表實現,只操作 Link_base*
,實現的是無類型的插入邏輯。
struct Link_base {Link_base* suc;Link_base* pre;
};struct List_base {Link_base* first;int sz;void add_front(Link_base* p);
};
?????????List<T>
是一個輕量級的包裝類,它提供類型安全,但實際的插入操作是調用的 List_base::add_front
。這樣,List<int>
、List<string>
這些實例共享一份核心代碼,只在包裝層做轉換和封裝。
template<typename T>
struct Link : Link_base {T val;
};template<typename T>
class List : List_base {
public:void put_front(const T& e) { add_front(new Link<T>{e}); }T& front() { static_cast<Link<T>*>(first)->val; }
};
三:總結? ? ? ?
? ? ? ? 所以為了保持 ABI 穩定,本規則建議將模板代碼與核心邏輯分離,使用非模板的基礎類或接口作為穩定的 ABI 邊界,模板只負責類型安全和包裝。這種做法可以避免因模板實例化導致的代碼膨脹和 ABI 不兼容問題。
??
????????