c++double-dispatch

What exactly happened that we need double dispatch/visitor in c++


I understand the implementation of the solution and the double dispatch/visitor pattern, however I don't understand what happens at compile time and run-time that we need this pattern.

For example this code:

#include <iostream>

class A {
public:
};
class B : public A {
};

class F {
public:
    virtual inline void operator()(const A&) const noexcept {
        std::cout << "FxA" << std::endl;
    }
    virtual inline void operator()(const B&) const noexcept {
        std::cout << "FxB" << std::endl;
    }
};

class G : public F {
public:
    virtual inline void operator()(const A&) const noexcept {
        std::cout << "GxA" << std::endl;
    }
    virtual inline void operator()(const B&) const noexcept {
        std::cout << "GxB" << std::endl;
    }
};

void by_const_ref(const F& f, const A& a) {
    f(a);
}

int main() {
    by_const_ref(F(), A());
    by_const_ref(F(), B());
    by_const_ref(G(), A());
    by_const_ref(G(), B());

    return 0;
}

Without double dispatch the second and fourth call to by_const_ref will not resolve B() into a A object.

From this article: https://en.wikipedia.org/wiki/Double_dispatch#Double_dispatch_in_C++ I understand that it involves name mangling and compile time and vtable resolution at run-time, but I didn't find how exactly.

For the name-mangling part I looked at the compiled object but didn't find anything special.

For the vtable I dumped it with g++ -fdump-lang-class and it didn't looked like there were much information there too.

Hence my request. I'd like to understand what exactly happened and maybe how to check this behavior (using tools like nm, checking the vtable, the machine code ?)


Solution

  • You went too deep, it's way simpler.

    C++ virtual functions enable dynamic dispatching based on the type of a single parameter, this. Double dispatching, as the name implies, is dynamic dispatching based on the type of two parameters. Since the language does not provide this feature, the Visitor pattern just uses the built-in single dispatching twice, using each dynamic parameter as this in turn.

    You could conceivably implement a Visitor performing triple dispatching or more by continuing this game of musical chairs until all of the dynamic parameters have been this once and been dispatched correctly before the final call.