簡體   English   中英

std::visit 如何處理多個變體?

[英]How does std::visit handle multiple variants?

std::visit 如何與 std::variant 一起工作的問題相關,但不是同一個問題?

為單個變體實現std::visit在概念上如下所示(在 C++ 偽代碼中):

template<class F, class... Ts>
void visit(F&& f, variant<Ts...>&& var) {
  using caller_type = void(*)(void*);
  caller_type dispatch[] = {dispatch_visitor(f, (INDEX_SEQUENCE))...};
  dispatch[var.index()](var);
};

基本上,我們設置了一個跳轉表,為我們的訪問者調用正確的調度程序。

對於多個變體,它似乎更復雜,因為對於這種方法,您需要計算所有變體備選方案的笛卡爾積,並可能模板數千個函數。 這是它的完成方式還是標准庫實現它的更好方式?

對於多個變體,它似乎更復雜,因為對於這種方法,您需要計算所有變體備選方案的笛卡爾積,並可能模板數千個函數。

目前有兩種多變量訪問的實現。

GCC在編譯時根據變體替代類型的個數構建多維function表,並在運行時通過多個索引訪問對應的訪問function。

// Use a jump table for the general case.
constexpr auto& __vtable = __detail::__variant::__gen_vtable< 
                             _Result_type, _Visitor&&, _Variants&&...>::_S_vtable;
auto __func_ptr = __vtable._M_access(__variants.index()...);
return (*__func_ptr)(std::forward<_Visitor>(__visitor),
                     std::forward<_Variants>(__variants)...);

MSVC 使用遞歸 switch-case來執行多變量訪問:

#define _STL_VISIT_STAMP(stamper, n)                                               \
    constexpr size_t _Size = _Variant_total_states<_Remove_cvref_t<_Variants>...>; \
    static_assert(_Size > (n) / 4 && _Size <= (n));                                \
    switch (_Idx) {                                                                \
        stamper(0, _STL_CASE);                                                     \
    default:                                                                       \
        _STL_UNREACHABLE;                                                          \
    }

這種 switch-case base 實現在變體數量較少或備選方案數量較少時具有更好的性能,這也使得 GCC 在其最近的補丁中使用這種方法處理簡單的情況,以減少 function 表的實例化。

switch (__v0.index())
{
  _GLIBCXX_VISIT_CASE(0)
  _GLIBCXX_VISIT_CASE(1)
  _GLIBCXX_VISIT_CASE(2)
  _GLIBCXX_VISIT_CASE(3)
  _GLIBCXX_VISIT_CASE(4)
  case variant_npos:
          // ...
}

更多實現細節可以參考以下兩篇 Michael Park 的博客:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM