Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compile-time elimination of if/else branch in C++

In the following code sample, the if statement depends on bool template parameter, which is a compile-time constant. Compilers handle this code differently:

  • MSVC fails with link error (which is what I expected), because the template function in else branch lacks specialisation for true template parameter value (even though it is never called).

  • GCC and Clang both compile without issues and run-time behaviour is correct. This is obviously because they evaluate the if statement at compile time and remove unused branches before linking.

The question is which behaviour is standard-compliant (or is it an undefined behaviour and both are correct in their own way)?

#include <iostream>

template<const bool condition>
struct Struct
{
    void print()
    {
        if (condition)
        {
            std::cout << "True\n";
        }
        else
        {
            printIfFalse();
        }
    }

private:
    void printIfFalse();
};

template <>
void Struct<false>::printIfFalse()
{
    std::cout << "False\n";
}

int main()
{
    Struct<true> withTrue{};
    withTrue.print();

    Struct<false> withFalse{};
    withFalse.print();

    return 0;
}
like image 621
Igor Tolmachov Avatar asked Mar 27 '20 11:03

Igor Tolmachov


Video Answer


1 Answers

All compilers behave correctly.

Your program is ill-formed, no diagnostic required, because you are odr-using Struct<true>::printIfFalse through the instantiation of Struct<true>::print() required from the call in withTrue.print();. A function that is odr-used outside of a discarded statement must have a definition in the program, see [basic.def.odr]/4, otherwise the program is ill-formed, no diagnostic required.

A discarded statement is what you get if you use if constexpr in a template and the statement is not in the chosen branch. So, what you can do to make the program well-formed is to use if constexpr instead of if. This is a C++17 feature.

like image 105
walnut Avatar answered Oct 29 '22 10:10

walnut