Search code examples
c++templatesoperators

Does C++ guarantee shortcutting for compile time constants?


I have a compile-time condition, using std::conditional<cond, TypeA, TypeB>. In my case, the condition is a disjunction, along the lines of SimpleCondition<T>::value || ComplexCondition<T>::value. In my case T is a list of length n, and I can show that SimpleCondition<T>::value can be processed in O(1) time, while ComplexCondition<T>::Value requires O(n) time. I would like to rely on shortcutting to ensure I don't compute the O(n) side every single time... assuming I can.

If these were runtime functions instead of compile time constants, it would be easy to show that simpleCondition(t) || complexCondition(t) will shortcut. Is shortcutting guaranteed for compile time constants too?

As a more extreme case, consider the case where SimpleCondition is being used to work around the halting problem. Perhaps ComplexCondition<T>::value can be proven to terminate for many values, but that proof is unavailable for cases where SimpleCondition<T>::value is true. In such a circumstance, this question of shortcutting would be the difference between a program that provably compiles and one that does not.


Solution

  • When evaluating SimpleCondition<T>::value || ComplexCondition<T>::value the compiler looks up and instantiates SimpleCondition<T> and ComplexCondition<T> and then looks up the value member. The instantiation is what actually does any compile time evaluation, so while the eventual (assuming they both are true) true || true would "short circuit", no extra work would need to be done at that point.

    The solution is to use std::disjunction.

    std::disjunction_v<SimpleCondition<T>, ComplexCondition<T>> gives essentially the same result, but will not instantiate ComplexCondition<T> if SimpleCondition<T>::value is true. This means if ComplexCondition<T> would have an error (e.g., an infinite recursion), or it would just take a lot of compile time resources to compute, they just won't happen.

    (And std::conjunction_v for the && case)