詳細的解說如何在編譯期做出一個具有多重型別的物件
神偷小吉從在S社工作的朋友K那裡幹來的程式碼
Code在此,本文要來一步一步拆解這段code在幹嘛
1
2
3
4
5
6
7
8
9let i = 11;
let b = false;
let s = std::string{"oh yes"};
let v = Multi{
[&] { return i; },
[&] { return b; },
[&] { return s; },
};首先我們可以看到本文主角Multi,一個神祕物件,初始化的時候吃了一個塞了三個不同return type的lambda的initialize list
- let的定義是#define let const auto
- 這個Multi是何方神聖?
1 | template <typename T> |
- Multi是一個struct,繼承了To
- 等等,這個如同財哥專業檳榔的繼承是怎麼回事?
- Keyword: variadic template
- 我們來看個範例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21struct A {
};
struct B {
};
struct C {
};
template <typename... Ts>
struct Multi : public Ts... {
};
int main() {
Multi<A, B, C> m ;
return 0 ;
} - 基本上Ts...表示你可以給很多個type,他會幫你自動補上",",like this
1
2
3
4template<>
struct Multi<A, B, C> : public A, public B, public C
{
};
- 我們來看個範例
- 所以
struct Multi : public To<Ts>...
被轉換成了- struct Multi : public To<Ts#1>, To<Ts#2>, ......
- 在這個例子中,Ts#n這些東西會變成什麼?
- struct Multi: public To<lambda#A>, To<lambda#B>嗎?
- 仔細看看To內部
1
2
3
4
5template <typename T>
struct To {
// ...
operator T() const { return f(); };
// ... - T是一個return type,看起來絕對不會是lambda
- 仔細看看To內部
- 中間似乎差了一個步驟......?
- User-defined deduction guides
- 我們仔細看一下有一段code
1
2template <typename... Ts>
Multi(Ts...) -> Multi<std::invoke_result_t<Ts>...>;- 這到底是什麼東西? function prototype?
- 非也! 這個可是C++17的新特性Class template argument deduction (CTAD)
- 其中的一個概念:User-defined deduction guides
- 人為的去教compiler如何實例化你的type
- 所以上面那段code是什麼意思?
- 這段code的意思是如果今天出現了一個type Multi(Ts#1, Ts#2,
......),我們會引導compiler把它變成
1
2
3
4
5Multi<
std::invoke_result_t<Ts#1>,
std::invoke_result_t<Ts#2>,
...
>
- 這段code的意思是如果今天出現了一個type Multi(Ts#1, Ts#2,
......),我們會引導compiler把它變成
- invoke_result_t會在compile tile推導callable的return type
- 這到底是什麼東西? function prototype?
- 統整一下上面所述,整個轉換的流程為(對應我們範例程式碼的行數)
- const auto v = Multi { lambda, lambda, lambda } ; [30.]
- Multi(lambda, lambda, lambda) ->
Multi<std::invoke_result_t
, std::invoke_result_t , std::invoke_result_t > [23.] - Multi(lambda, lambda, lambda) -> Multi<int, bool, std::string>[23.]
- Multi<int, bool, std::string> -> struct Multi : public To<int>, To<bool>, To<std::string>[20.]
- 我們仔細看一下有一段code
- 接下來情況就很明朗了,我們得到了一個有多重繼承的物件,最後就是看static_cast<>轉成誰,就會變成誰,Magic!
延伸閱讀
小結
- 我說完了,我說 完了