Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to use constexpr function template to re-write a very long switch-case efficiently?

To easily re-write a big switch-case, I’m trying constexpr function template like this (it’s only a simplified version with just cout):

#include <iostream>

template<int T>
constexpr void bigSwitchCase(const int idx)
{
    if (T == 1 && T == idx)
    {
        std::cout << 1 <<std::endl;
        return;
    }



    if (T == idx)
    {
        std::cout << T << std::endl;
    }
    else if (T > 1)
    {
        bigSwitchCase<T - 1>(idx);
    }

    return;
}

template<>
void bigSwitchCase<1>(const int idx)
{
    if (1== idx)
    {
        std::cout << 1 <<std::endl;
        return;
    }
}

int main()
{
    bigSwitchCase<64>(15);
    //bigSwitchCase<4096>(15);
    return 0;
}

but the problem is it is not producing as fast code as below version:

switch(idx)
{
case 1: std::cout << 1 << std::endl; break;
case 2: std::cout << 2 << std::endl; break;
...
case 4096: std::cout << 4096 << std::endl; break;
default:
}

because if-else parts in the constexpr function contains idx input which is not constexpr hence the if-else can not be made constxpr. But the switch-case elements are all cosntants.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

So, the function produces a loop instead and checks against idx value, according to compiler-generated assembly codes. I need it to directly jump to the point that does the work instead of looping.

How to produce efficient code using only constexpr function templates (because real work includes plain arrays with compile-time sizes) with a run-time integer input (about ~4000 upper limit and 1 lower limit)?

>Solution :

You can give the compiler a hint that you want a jump table instead of iteration through all cases by implementing it in that form yourself:

template<int I>
void doit()
{
    std::cout << I <<std::endl;
    return;
}

template<int N>
void bigSwitchCase(int idx) {
    static constexpr auto jumptable =
        []<int... Is>(std::integer_sequence<int, 0, Is...>){
            return std::array{doit<Is>...};
        }(std::make_integer_sequence<int, N+1>());
    if(idx >= 1 && idx <= N)
        jumptable[idx-1]();
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading