I'd like to have a type that behaves differently whether it is used in a constexpr context.
See this example:
#include <cstdio>
#include <type_traits>
template <bool IS_CONSTANT_EVAL>
struct Bar;
template <>
struct Bar<false> {
constexpr int doIt() const {
return 0;
}
};
template <>
struct Bar<true> {
constexpr int doIt() const {
return 1;
}
};
constexpr int foo() {
if (std::is_constant_evaluated()) {
Bar<true> v;
return v.doIt();
} else {
Bar<false> v;
return v.doIt();
}
}
int main() {
int rt = foo();
constexpr int ce = foo();
printf("Runtime: %d ConstEval: %d \n", rt, ce);
}
In this example, foo behaves differently whether it's called from a constexpr context, because the specialization depends on constexpr-ness, so it prints:
Runtime: 0 ConstEval: 1
But if I try to simplify this to:
constexpr int foo() {
Bar<std::is_constant_evaluated()> v;
return v.doIt();
}
It doesn't work anymore, because std::is_constant_evaluated() always returns true as a template argument.
Even, I'd like to have an even simpler foo, something like this:
constexpr int foo() {
Bar v;
return v.doIt();
}
So Bar itself should deal with constexpr-ness somehow, I don't want to repeat std::is_constant_evaluated() at each Bar usage.
Is it possible to do this?
Note: I actually don't want to have different behavior, just different implementation. Because of constexpr limitations, I need to have different implementations of Bar depending on constexpr-ness. For example, memcpy and reinterpret_cast make expressions not constant. So, if Bar is used in a constant expression, I need to use some constexpr-compatible technique to replace memcpy or reinterpret_cast.
Note 2: I really need different Bar definitions, it's not just doIt that needs to differ. Replacing memcpy and reinterpret_cast needs extra members in Bar if it is used in a constant expression.