Forcing a constant expression to be evaluated during compile-time? - c++

A few days ago I asked by which criteria the compiler decides whether or not, to compute a constexpr function during compile time.
When does a constexpr function get evaluated at compile time?
As it turns out, a constexpr is only evaluated during compile-time, if all parameters are constant expressions and the variable you are assigning it to is are constant expression as well.
template<typename base_t, typename expo_t>
constexpr base_t POW(base_t base, expo_t expo)
{
return (expo != 0 )? base * POW(base, expo -1) : 1;
}
template<typename T>
void foobar(T val)
{
std::cout << val << std::endl;
}
int main(int argc, char** argv)
{
foobar(POW((unsigned long long)2, 63));
return 0;
}
If what I was told is true, this code example is very impratical, since foobar doesn't take a constexpr (you can't use consexpr for parameters for some reason), POW gets evaluated during runtime, even though it would have been possible to compute it during compile-time. The obvious solution for forcing a compile-time evaluation would be this:
auto expr = POW((unsigned long long)2, 63);
foobar(expr);
This however forces me to use an additional line of code, which shouldn't be necessary each time I want to make sure a constexpr gets evaluated during compile-time. To make this a little more convenient, I've come up with the following dubious macro:
#define FORCE_CT_EVAL(func) [](){constexpr auto ___expr = func; return std::move(___expr);}()
foobar(FORCE_CT_EVAL(POW((unsigned long long)2, 63)));
Despite the fact that it works just fine, I feel like as if something isn't right about it. Does creating an anonymous lambda impact performance? Does returning by rvalue reference actually move the expression to the function parameter? How does std::move impact performance? Is there a better one liner solution for this?

Just to not leave it buried in comments:
#include <type_traits>
#define COMPILATION_EVAL(e) (std::integral_constant<decltype(e), e>::value)
constexpr int f(int i){return i;}
int main()
{
int x = COMPILATION_EVAL(f(0));
}
EDIT1:
One caveat with this approach, constexpr functions can accept floating-point and be assigned to constexpr floating-point variables, but you cannot use a floating-point type as a non-type template parameter. Also, same limitations for other kinds of literals.
Your lambda would work for that, but I guess you would need a default-capture to get meaningful error message when non-constexpr stuff get passed to the function. That ending std::move is dispensable.
EDIT2:
Err, your lambda approach doesn't work for me, I just realized, how it can even work, the lambda is not a constexpr function. It should not be working for you too.
It seems there's really no way around it but initializing a constexpr variable in local scope.
EDIT3:
Oh, ok, my bad, the purpose of the lambda is just the evaluation. So it's working for that. Its result, instead, is which is unusable to follow another compilation time eval.
EDIT4:
On C++17, lambdas now can be used in constexpr contexts, so the limitation referred to in EDIT2/EDIT3 is removed! So the lambda solution is the correct one. See this comment for more information.

Related

Are there benefits to using a constexpr variable that is never intended to be used in a constant expression?

This is a follow up question to this one.
From one of the answers in the question linked, it makes sense that the purpose of declaring a variable as constexpr is not truly to inform the compiler of the possibility of using that variable as a constant expression (although this is the end behavior of the compiler) but rather to convey to other programmers the intent that the variable can be used in a constant expression. My question is whether there is any benefit, performance or otherwise, to declaring a variable as constexpr if the variable is not intended to be used in a constant expression (e.g. a constant member variable of a class which only appears in non-constant expressions with other non-const member variables). Also assume that this is not for an embedded system.
I work with code where the previous developers seem to use constexpr like it's candy even when it's not clear that the intent is for the variable to be used in a constant expression (like in the example from the previous paragraph). I want to know if they knew something that I don't.
but rather to convey to other programmers the intent that the variable can be used in a constant expression.
This is a matter of opinion but I beg to differ.
In principle, I think it is better to make everything that can be known and computed at compile time a constexpr. The fact that it can also be used in constant expressions is a side benefit. Use of constexpr may have performance related benefits too.
The key point I want to make is that "the value is known at compile time" is a characteristic of the variable/data. It is better to capture that characteristic by using a language provided feature. The only time one could justify not using it will be if there are any adverse side effects.
Yes, constexpr variables are useful for more than just conveying intent and using in other constant expressions.
If you mark a variable constexpr, the compiler will enforce that it itself is initialized with a constant expression. You can use this to make sure that the things you expect to be evaluated at compile time actually are. For example:
constexpr int constexpr_function() { return 123; }
int expensive_runtime_function() { return 123; }
void f()
{
constexpr int good1 = constexpr_function(); // OK.
// constexpr int good2 = expensive_runtime_function(); // Good: error.
const int bad1 = constexpr_function(); // OK.
const int bad2 = expensive_runtime_function(); // Bad: unexpected runtime cost.
}

C++ constexpr - Value can be evaluated at compile time?

I was reading about constexpr here:
The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time.
When I first read this sentence, it made perfect sense to me. However, recently I've come across some code that completely threw me off. I've reconstructed a simple example below:
#include <iostream>
void MysteryFunction(int *p);
constexpr int PlusOne(int input) {
return input + 1;
}
int main() {
int i = 0;
MysteryFunction(&i);
std::cout << PlusOne(i) << std::endl;
return 0;
}
Looking at this code, there is no way for me to say what the result of PlusOne(i) should be, however it actually compiles! (Of course linking will fail, but g++ -std=c++11 -c succeeds without error.)
What would be the correct interpretation of "possible to evaluate the value of the function at compile time"?
The quoted wording is a little misleading in a sense. If you just take PlusOne in isolation, and observe its logic, and assume that the inputs are known at compile-time, then the calculations therein can also be performed at compile-time. Slapping the constexpr keyword on it ensures that we maintain this lovely state and everything's fine.
But if the input isn't known at compile-time then it's still just a normal function and will be called at runtime.
So the constexpr is a property of the function ("possible to evaluate at compile time" for some input, not for all input) not of your function/input combination in this specific case (so not for this particular input either).
It's a bit like how a function could take a const int& but that doesn't mean the original object had to be const. Here, similarly, constexpr adds constraints onto the function, without adding constraints onto the function's input.
Admittedly it's all a giant, confusing, nebulous mess (C++! Yay!). Just remember, your code describes the meaning of a program! It's not a direct recipe for machine instructions at different phases of compilation.
(To really enforce this you'd have the integer be a template argument.)
A constexpr function may be called within a constant expression, provided that the other requirements for the evaluation of the constant expression are met. It may also be called within an expression that is not a constant expression, in which case it behaves the same as if it had not been declared with constexpr. As the code in your question demonstrates, the result of calling a constexpr function is not automatically a constant expression.
What would be the correct interpretation of "possible to evaluate the value of the function at compile time"?
If all the arguments to the function are evaluatable at compile time, then the return value of the function can be evaluated at compile time.
However, if the values of the arguments to the function are known only at run time, then the retun value of the function can only be evaluated at run time.
Hence, it possible to evaluate the value of the function at compile time but it is not a requirement.
All the answers are correct, but I want to give one short example that I use to explain how ridiculously unintuitive constexpr is.
#include <cstdlib>
constexpr int fun(int i){
if (i==42){
return 47;
} else {
return rand();
}
}
int main()
{
int arr[fun(42)];
}
As a side note:
some people find constexpr status unsatisfying so they proposed constexpr! keyword addition to the language.

How to make sure in a constexpr function taking an array that the array is NULL-terminated?

The following code is meant to create sort of a trivial hash of a string up to 8 characters long:
#include <type_traits>
#include <cstdint>
#include <iostream>
template<std::size_t N, std::size_t n=N>
constexpr typename std::enable_if<N<=9 && n==0,
uint64_t>::type string_hash(const char (&)[N])
{
return 0;
}
template<std::size_t N, std::size_t n=N>
constexpr typename std::enable_if<N<=9 && n!=0,
uint64_t>::type string_hash(const char (&array)[N])
{
return string_hash<N,n-1>(array) | ((array[n-1]&0xffull)<<(8*(n-1)));
}
For normal string literals and constexpr NULL-terminated strings it does indeed work normally. But if I do something like this:
constexpr char s2[] = {1,2,3,4,5,6,7,8,9};
std::cout << string_hash(s2) << "\n";
, the output will be the same as for the string "\x1\x2\x3\x4\x5\x6\x7\x8". I've tried adding a static_assert(array[N-1]==0,"Failed"); in the definition of string_hash, but the compiler says that array[N-1] is not a constant-expression. I then tried declaring the parameter constexpr, but the compiler said a parameter can't be declared constexpr.
How can I then do this check?
Please keep in mind that although constexpr functions can be used at compile time, they don't need to be. You cannot add any static assertions on runtime parameters, because the static assertion would be impossible to evaluate when the parameters are not known at compile time.
What you can do is the same thing you can do for non-constexpr functions: throw something. This doesn't prevent your function from being called with invalid input, but does prevent silent wrong results. And when your function is used in a context requiring a constant expression, the compiler will correctly detect it as not returning a constant value.
The body of a constexpr function needs to be a single return statement in C++11, but you can still fit it in there:
return array[N-1] ? throw "bad!" : <your current return expression here>;
Do pick something better to throw though.
The reason why the compiler is complaining is because the array is unknown at the time when string_hash<N,n> function is being instantiated. static_cast is evaluated when instancing, and not when invoking (even if it is constexpr function).
Notice that there will be exactly one function created for each pair of <N,n> values. If you use two constexpr strings of same length, exactly same instance of string_hash will be used, but depending on the argument array[N-1] may give a different result.
I will continue to search for a precise answer to your question if it is needed. However, as a "quick fix", may I suggest changing the hash function so that it always include the last character in the computation, be it 0 or not?
Update:
after doing some digging, I learned that some kind of constexpr_assert is what you probably want in your case and it is currently missing from the standard. Hopefully they will add it in the future. You may want to check:
g++ doesn't compile constexpr function with assert in it
Alternative to asserts for constexpr functions
http://ericniebler.com/2014/09/27/assert-and-constexpr-in-cxx11

constexpr vs const: Will use a constexpr instead of const better help compile to optmize?

Will use a constexpr instead of const better help compile to optmize? I have some value that are constant. I could use an enum instead of but they aren't all of same type and I don't want to use #defines for ovious reasons. They are declared like below code. My question is: if I use constexpr will it increase possibilities to compiler replace the value where it's used by the literal constant value or it doesn't differ if I use const? I know it's up to each compiler if does or doesn't the optmization but a "general" answer as it behave in most compiler is very welcome. Also, assuming the result are different for simple locals like this it's different too if instead of they are member of a struct/class? is const folding most hard to be performed in this cases?
e.g,
int foo()
{
constexpr int x = 10;
constexpr int y = x * 3;
do_domsething(y + n);
}
versus
int foo()
{
const int x = 10;
const int y = x * 3;
do_domsething(y + n);
}
Today, constexpr is still pretty new and might fall through some optimization cracks. Calculation of the variable's own value is required to be performed at compile time, of course. In the long run, I'd expect the same optimization opportunities for each. Obviously when that happens is compiler-specific.
Just use whichever one has clearer meaning to you and anyone else working on the code, not only in terms of behavior but also intent.
Among other things, note that constexpr guarantees the constant has the same value always, whereas const allows it to have a different value each time initialization is reached (it can't be changed except by initialization, of course). But nearly every compiler on the planet will determine that for your example, the values really are constant.
One more thing: constexpr compile-time evaluation (like template argument calculation) is active even when optimizations are disabled.

Is it possible to make a function behave differently for constant argument or variable argument?

For example, factorial(n), if the argument is a constant (expression), then the result is deterministic, and can be done at compile time (by using template meta-programming).
Is that possible to just write a single function such that whenever it is called, if the argument is a constant, then the result will be computed at compile time, if it is a variable, then it will do the computation at run time?
This is precisely what constexpr functions exist for. constexpr functions were introduced in C++11. When invoked with constant expressions that can be evaluated at compile-time, they tend to be evaluated at compile time (and sometimes you can force this to occur). However, in general it is not possible to provide a guarantee. Otherwise, they are evaluated at run-time (and you can invoke them just as regular functions with constant or non-constant arguments computed at run-time).
Apart from the lack of guarantee of their compile-time evaluation, a constexpr function has constraints though: it must consist of only one single return statement, so if you're looking for a way to perform computations of any complexity, this won't fit your needs. Nevertheless, constexpr functions are probably the closest thing to what you are looking for.
Since you mention the example of the factorial() function, here is what this would look like with a constexpr function:
#include <iostream>
using namespace std;
constexpr int factorial(int n)
{
return (n == 0) ? 1 : factorial(n - 1);
}
int foo()
{
int result = 1;
// do some processing...
return result;
}
int main()
{
int v[factorial(5)]; // Evaluated at compile-time
cout << factorial(foo()); // Evaluated at run-time
}