Imagine next code that doesn't compile:
#include <type_traits>
#include <iostream>
int main() {
struct A { int i = 123; };
struct B { int j = 456; };
B x;
if constexpr(std::is_same_v<decltype(x), A>)
std::cout << "A: " << x.i;
else if constexpr(std::is_same_v<decltype(x), B>)
std::cout << "B: " << x.j;
}
By this code I wanted to have several branches of code different for different types. In general I want different branches not only for certain type but for any constexpr condition.
Code above is uncompilable because looks like that compiler always tries to compile all if-constexpr branches even if they have compile time false condition.
Of cause I can solve task above by using template structs specialization like in compilable code below:
#include <type_traits>
#include <iostream>
template <size_t Id>
struct Code;
template <>
struct Code<0> {
template <typename AT>
void operator()(AT & x){
std::cout << "A: " << x.i;
}
};
template <>
struct Code<1> {
template <typename BT>
void operator()(BT & x){
std::cout << "B: " << x.j;
}
};
int main() {
struct A { int i = 123; };
struct B { int j = 456; };
B x;
Code<std::is_same_v<decltype(x), A> ? 0 : std::is_same_v<decltype(x), B> ? 1 : -1>()(x);
}
But the last solution has several drawbacks - 1) it is much more wordy, needs more lines of code. 2) it needs Code struct to be defined globally, because template structs can be defined only globally. 3) it needs all needed arguments for code to work to be passed/forwarded to operator() call.
constexpr variant looks much more elegant and is more intuitive to use. Is there any way to solve such task with if-constexpr? To force compiler not to compile compile-time-false-branches.