Tag Dispatching

The tag dispatching is a widely used idiom in C++ development. It used extensively in the following chapters of this book.

Let's try to compile test_cpp_tag_dispatch application in embxx_on_rpi project and take a look at the code generated by the compiler.

struct Tag1 {};
struct Tag2 {};

class Dispatcher
{
public:

    template <typename TTag>
    static void func()
    {
        funcInternal(TTag());
    }

private:
    static void funcInternal(Tag1 tag);
    static void funcInternal(Tag2 tag);

};

Somewhere in the main function:

Dispatcher::func<Tag1>();
Dispatcher::func<Tag2>();

The code generated by the compiler looks like this:

000080fc <main>:
    80fc:    e92d4008     push    {r3, lr}
    8100:    e3a00000     mov    r0, #0
    8104:    ebfffff3     bl    80d8 <_ZN10Dispatcher12funcInternalE4Tag1>
    8108:    e3a00000     mov    r0, #0
    810c:    ebfffff2     bl    80dc <_ZN10Dispatcher12funcInternalE4Tag2>
    ...

Although the Tag1 and Tag2 are empty classes, the compiler still uses integer value 0 as a first parameter to the function.

Let's try to optimise this redundant mov r0, #0 instruction away by making it visible to the compiler that the tag parameter is not used:

class Dispatcher
{
public:

    template <typename TTag>
    static void otherFunc()
    {
        otherFuncInternal(TTag());
    }

private:

    static void otherFuncInternal(Tag1 tag)
    {
        static_cast<void>(tag);
        otherFuncTag1();
    }

    static void otherFuncInternal(Tag2 tag)
    {
        static_cast<void>(tag);
        otherFuncTag2();
    }


    static void otherFuncTag1();
    static void otherFuncTag2();
};

Somewhere in the main function:

Dispatcher::otherFunc<Tag1>();
Dispatcher::otherFunc<Tag2>();

The code generated by the compiler looks like this:

000080fc <main>:
    ...
    8110:    ebfffff2     bl    80e0 <_ZN10Dispatcher13otherFuncTag1Ev>
    8114:    ebfffff2     bl    80e4 <_ZN10Dispatcher13otherFuncTag2Ev>

In this case the compiler optimises away the tag parameter.

Based on the above we may make a CONCLUSION: When tag dispatching idiom is used, the function that receives a dummy (tag) parameter should be a simple inline wrapper around other function that implements the required functionality. In this case the compiler will optimise away the creation of tag object and will call the wrapped function directly.

Last updated