考慮以下兩個片段:
// Option (1).
boost::mp11::mp_with_index<N>(i,
[&](const auto i){ function<i>(/* args... */); });
和
// Option (2).
inline static const std::array<std::function<void(/* Args... */)>, N>
functionArray{function<0>, ..., function<N-1>};
functionArray[i](/* args... */);
其中N是大約在 [0, 20] 范圍內的編譯時間大小,i是0和之間的運行時索引N-1,并且template <size_t I> function(/* Args... */)是具有已知簽名的模板函式。這兩個選項中哪個是最快的?
注意:我知道這boost::mp11::mp_with_index基本上創建了一個 switch 陳述句,允許將運行時索引轉換為編譯時索引。這引入了一些間接性,但我希望這不會太昂貴。同樣,我知道std::function由于型別擦除而引入了一些間接性。我的問題是:兩種間接型別中哪一種最有效?
uj5u.com熱心網友回復:
std::array<std::function<void(Args...)>, N>與純指標陣列相比,可能會引入一些開銷std::array<void(*)(Args...), N>。
在https://godbolt.org/z/a8z9aKs7P查看生成的程式集,可以進行以下觀察:
boost::mp11::mp_with_index被編譯成一個分支表,其中包含 N 個不同指令的 N 個地址,這些指令function<I>在跳轉到時簡單地呼叫。因此,它將在分支表中查找地址,跳轉到該地址,然后再次跳轉到所需的函式。
這個分支表可以通過簡單地存盤 的地址來簡化function<I>,只需要一次跳轉。這是當你有一個函式指標陣列會發生什么,該陣列基本上是一個分支表。
std::function類似,但呼叫 astd::function比呼叫常規函式指標稍微復雜一些。
注意 clang 在-O2甚至優化這個方面很糟糕-O3。boost::mp11::mp_with_index<N>實際上是一堆 if/else 陳述句,應該很容易編譯,就好像它是 a 一樣switch,但是 clang 沒有做到這一點(并留下N“比較和條件跳轉”指令)。函式指標陣列是這里唯一的好選擇。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/394773.html
