Sometimes there is a need to enforce computation of some expression at compile time.
E.g. if we have f(/*some args*/)
function that is constexpr
, it can be computed both at compile and run time. But if we want to force it to be compile-time one way is to assign its value to constexpr
constant:
constexpr auto x = f(/*some args*/);
But what to do if we want it to be used as a part of complex expression, whole expression can be run-time value, but it is interesting sometimes to compute some parts of expression at compile time if it gives some noticeable performance improvements (or for other reasons stated below). E.g. expression:
int x = 123;
int y = x + 456 * f(/*some args*/);
In the expression above one way to enforce compile time computation of f
is to use std::integral_constant
:
int x = 123;
int y = x + 456 * std::integral_constant<int, f(/*some args*/)>::value;
But maybe there is some shorter way to do it in standard C++? E.g. maybe there is a kind of constexpr operator: 456 * constexpr(f(/*some args*/))
?
The shortest form I figured out:
template <auto V>
constexpr inline auto ce = V;
int y = x + 456 * ce<f(/*some args*/)>;
This solution is nice, but maybe there is already similar to ce<...>
templated constant inside standard C++ library? So that I don't invent new classes/functions if there are some standard ones. Because current standard class std::integral_constant
needs specifying type as first argument and also needs ::value
, which is not very short way to write.
Why do I bother about enforcing compile time? Because of next code:
Try it online!
struct S {
consteval bool has42() const {
return i == 42;
}
int i = 0;
};
template <auto V>
constexpr inline auto ce = V;
int main() {
constexpr S s;
int z = 10;
auto x = z + int(ce<s.has42()>); // OK
auto y = z + int(s.has42()); // Compile error
}
Code above works perfectly well under CLang, but under latest MSVC line with auto y....
doesn't compile with error error C7595: 'S::has42': call to immediate function is not a constant expression
. Line with auto x.....
compiles correctly on both CLang/MSVC due to use of ce<...>
which enforces compile time computation.
Seems that MSVC supposes all expressions to be run-time values if they are not stated as constexpr explicitly. Of cause although they are marked as run-time values still compiler does all optimizations and probably compile time code will not be different from run-time.
question from:
https://stackoverflow.com/questions/65936269/standard-way-to-enforce-constexpr-for-parts-of-complex-expression-in-c