API Design
看了lexy的程式碼之後,對其API Design很有興趣
其中有一個設計
1 | template <typename Fn> |
這API的重點
- 我們只希望有一個Root
parse_state
- 只能透過 Util function
map
,可以創建另一個placeholder_base的subclass
lexy採用的是Partial template specialization方案來應對這個設計,不過這方案有個缺點,大量重複的程式碼
以上面的例子來看,operator()
的內容幾乎一樣,如果功能更多的話,可能會有更多類似但卻不相同的函數出現,可能增加維護的難度deduce this
deduce this的教學文章很多了,拾人牙慧也沒什麼意思
雖然不確定是否是最佳解,不過可以試試看設計這樣的API這邊的map跟lexy上面的map差不多1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16struct Base {
template <typename Self>
decltype(auto) operator()(this Self&& self) {
// Shared common logic
if constexpr (std::is_same_v<std::decay_t<Self>, Base>) {
} else {
}
}
template <typename Self>
requires std::is_same_v<std::decay_t<Self>, Base>
void test1(this Self&& self) {
}
};
struct Derived : public Base {};
constexpr auto parse_state = Base{}; - 只能透過
parse_state
來使用util functionmap
而operator()
就能共用大部分的邏輯了
不過這方法也是有缺點,對邊義氣版本的要求很高 - gcc目前要14才有支援
- clang目前也是到18才支持
- MSVC至少要17.2
CRTP
在寫完後不久,才想起CRTP也可以解決這問題
1 | template <typename Derived = void> |
不過比起deduce this,可以要麻煩一點