Suppose I have this function:
template<typename Side>
int GetSide(std::pair<int, int> i)
{
if (Side::mIsLeft)
return i.first;
else
return i.second;
}
I see that if mIsLeft
is const
(even not constexpr
) compiler (gcc/clang) won't generate any branch:
int GetSide<LeftSide>(std::pair<int, int>):
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-16], rdi
mov eax, DWORD PTR [rbp-16]
pop rbp
ret
In contrast to when mIsLeft
was NOT const
, which a branch would be generated (as expected.)
Now, my question is: Is this behavior (not generating a branch) enforced by standard, or guaranteed in anyway? Or it's just compiler seeing the opportunity and using it? (this is generated even in -O0
) What if mIsLeft
is constexpr
would that change anything?
You can check the code here on godbolt .
Why do I care? Before finding this, for a situation like this, I'd use enable_if
and have two different template specialization to avoid the unnecessary branch, but this can simplify lots of code.
No, the standard doesn't specify how compilers should generate code. Compilers are allowed to emit a branch even if the condition is a compile-time constant.
On the other hand, these days, optimizing compilers do their best to remove unnecessary branches, so it can be considered a compiler bug, if a compile-time-constant based if
doesn't get optimized away.
The details of your specific case are not completely known to us, but in general the answer is no. A const variable can of course be initialized with something that is not known at compile time, eg user input.
You should use a constexpr value and an if constexpr check (if possible in your code base).
Using if constexpr you would discard the branch you don't go in.
Constexpr If
The statement that begins with if constexpr is known as the constexpr if statement.
In a constexpr if statement, the value of condition must be a contextually converted constant expression of type bool. If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.
The return statements in a discarded statement do not participate in function return type deduction:
https://en.cppreference.com/w/cpp/language/if
More doc here: https://blog.tartanllama.xyz/if-constexpr/
Example here:
struct LeftSide
{
static constexpr bool mIsLeft=true;
};
struct RightSide
{
static constexpr bool mIsLeft=false;
};
template<typename Side>
int GetSide(std::pair<int, int> i)
{
if constexpr (Side::mIsLeft)
return i.first;
else
return i.second;
}
int main()
{
std::cout<<GetSide<LeftSide>({1,2})<<std::endl;
std::cout<<GetSide<RightSide>({3,4})<<std::endl;
return 0;
}
Output:
1
4
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.