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.
When evaluating
SimpleCondition<T>::value || ComplexCondition<T>::valuethe compiler looks up and instantiatesSimpleCondition<T>andComplexCondition<T>and then looks up thevaluemember. The instantiation is what actually does any compile time evaluation, so while the eventual (assuming they both aretrue)true || truewould "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 instantiateComplexCondition<T>ifSimpleCondition<T>::valueistrue. This means ifComplexCondition<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_vfor the&&case)