Compile Time “if” statement

Share the Article

Compile time “if” syntax is available from C++17 . This makes the compiler to evaluate the given “if” expression during compilation phase. This evaluation then decides whether the body of “if” part or “else” part shall generate the code. The other part is ignored by compiler. However, compiler performs basic syntax check in the other part.

The syntax uses “constexpr” keyword just after the “if” keyword.

Weird behavior with run-time “if”

When return type of a function is “auto” type, then a regular “if” statement sometimes get into problems. For example, when in such function, both “if” and “else” parts are present, then return type should be same in both parts.

Return type deduction for function “fun” shall fail in following code, because, the “if” part returns an integer and “else” returns a non-integer. This failure happens even though, the “else” part here never needs to be used.

#include <iostream> //main header using namespace std; //namespace auto funda() { const int xvar = 1; const int yvar = 3; if ((xvar+yvar) == 4) //No constexpr { cout << "if condition" << endl; return 7; } else { cout << "else condition" << endl; return 2.1; } } int main() { auto xvar = funda(); cout << xvar << endl; return 0; }

Output

g++ compiler error in C++17, inconsistent deduction

Compile-time “if” shall resolve

The compile time “if” shall evaluate the expression at compile time and therefore, it will simply ignore the “else” part return statement.

#include <iostream> //Main header using namespace std;//namespace auto funda() { const int xvar = 1; const int yvar = 3; if constexpr((xvar+yvar) == 4) { cout << "if condition" << endl; return 7; } else { cout << "else condition" << endl; return 2.1; } } int main() { auto xvar = funda(); cout << xvar << endl; return 0; }

Output

g++ compilation using constexpr "if"

Same example, with no “else” part

In following example, the exit path from function “fun” is from two places. First is from the “if” body and second is from return statement in last line. Since, any of the path is possible, therefore, compiler shall again generate an error due to ambiguity in deducing return type.

#include <iostream> //main header using namespace std; //namespace auto funda() { const int xvar = 1; const int yvar = 3; if ((xvar+yvar) == 4) //no constexpr { cout << "if condition" << endl; return 7; } return 2.1; } int main() { auto xvar = funda(); cout << xvar << endl; return 0; }
g++ error : inconsistent deduction for auto

Special behavior with compile-time “if”

The compile-time “if” shall not resolve the problem as it had done in last example. This is because, still the return type deduction will be ambiguous. Please note that the condition in “if” is always going to be true. Therefore, the return statement in the “if” body shall definitely be considered to deduce function return. However, the catch is that the compiler shall also consider second return statement which is located outside any condition.

The compiler shall generate same error in following code even when compile-time if is present.

auto funda() { const int xvar = 1; const int yvar = 3; if constexpr ((xvar+yvar) == 4) { cout << "if condition" << endl; return 7; } return 2.1; }

With negative constexpr “if” condition

Only when the “if” condition becomes false, then compile-time “if” shall ignore the return statement in the ‘if’ part body. In following case, the compiler shall only use the return statement outside the “if” construct.

Therefore, following example shall compile and work successfully.

auto funda() { const int xvar = 1; const int yvar = 3; if constexpr ((xvar+yvar) != 4) //false at compile-time { cout << "if condition" << endl; return 7; } return 2.1; }

Using constexpr “if” in a template function

Just like in previous example, where the return type was “auto”, the behavior is very similar in templates.

Due to same reason, the following example shall not compile with run-time “if”.

#include <iostream> //main header using namespace std; //namespace template <typename T> auto funda(T arg) { if (sizeof(arg) == 4) //no constexpr { return 7; } return 2.1; } int main() { auto xvar = funda<double>(3.4); cout << xvar << endl; return 0; }

Compiler Output

g++ compiler error: inconsistent deduction

However with compile time “if”, things will work with “fun<double>” instantiation

template <typename T> auto funda(T arg) { if constexpr(sizeof(arg) == 4) //false for double { return 7; } return 2.1; }

Two return types in two instantiation of templates

The above concept is used in following example where return type of template function is different in two different instantiations.

#include <iostream> //main header using namespace std; //namespace template <typename T> auto funda(T arg) { if constexpr(sizeof(arg) == 4) //case of funda<int> { return 7; } else //case of funda<double> { return 3.1; } } int main() { auto x1 = funda<double>(3.4); cout << x1 << endl; auto x2 = funda<int>(3); cout << x2 << endl; return 0; }

Output

g++ compilation success with constexpr

Main Funda: compile-time “if” evaluates the condition during compile time

Related Topics:

Lambda in C++11
Lambda in C++14
What are the drawbacks of using enum ?
Which member functions are generated by compiler in class?
How to stop compiler from generating special member functions?
Compiler Generated Destructor is always non-virtual
How to make a class object un-copyable?
Why virtual functions should not be called in constructor & destructor ?
Explaining C++ casts
How pointer to class members are different ?
How std::forward( ) works?
Rule of Three
How std::move() function works?
What is reference collapsing?
How delete keyword can be used to filter polymorphism
emplace_back vs push_back


Share the Article

Leave a Reply

Your email address will not be published. Required fields are marked *