Is there any hope to call a common base class method on a std::variant efficiently?

前端 未结 1 1749
不知归路
不知归路 2020-12-30 04:08

The way std::variant dispatches to different visitor methods when std::visit is called is pretty reasonable when the variant alternatives are compl

相关标签:
1条回答
  • 2020-12-30 04:44

    For what it's worth, a totally handrolled visit with a switch does pretty well:

    // use a code generator to write out all of these
    template <typename F, typename V>
    auto custom_visit(F f, V&& v, std::integral_constant<size_t, 2> )
    {
        switch (v.index()) {
        case 0: return f(std::get<0>(std::forward<V>(v)));
        case 1: return f(std::get<1>(std::forward<V>(v)));
    #ifdef VALUELESS
        case std::variant_npos: {
            []() [[gnu::cold, gnu::noinline]] {
                throw std::bad_variant_access();
            }();
        }
    #endif
        }
        __builtin_unreachable();
    
    }
    
    template <typename F, typename V>
    auto custom_visit(F f, V&& v) {
        return custom_visit(f, std::forward<V>(v),
            std::variant_size<std::decay_t<V>>{});
    }
    

    Which you'd use like:

    int getBaseMemVariant2(Foobar& v) {
      return custom_visit([](Base& b){ return &b; }, v)->getBaseMember();
    }
    

    With VALUELESS, this emits:

    getBaseMemVariant2(std::variant<Foo, Bar>&):
        movzx   eax, BYTE PTR [rdi+8]
        cmp     al, -1
        je      .L27
        cmp     al, 1
        ja      .L28
        mov     eax, DWORD PTR [rdi]
        ret
    .L27:
        sub     rsp, 8
        call    auto custom_visit<getBaseMemVariant2(std::variant<Foo, Bar>&)::{lambda(Base&)#1}, std::variant<Foo, Bar>&>(getBaseMemVariant2(std::variant<Foo, Bar>&)::{lambda(Base&)#1}, std::variant<Foo, Bar>&, std::integral_constant<unsigned long, 2ul>)::{lambda()#1}::operator()() const [clone .isra.1]
    

    Which is pretty good. Without VALUELESS, this emits :

    getBaseMemVariant2(std::variant<Foo, Bar>&):
        mov     eax, DWORD PTR [rdi]
        ret
    

    as desired.

    I don't really know what conclusion, if any, to draw from this. Clearly, there's hope?

    0 讨论(0)
提交回复
热议问题