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

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.

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.
}

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

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
}

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

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.

Folding away assertions in C++ class?

So, in a non-class type of situation, I can do something like this:
int val_to_check = 0;
int some_func(int param) {
assert(val_to_check == 0);
return param*param+param;
}
int main() {
printf("Val: %i\n", some_func(rand()));
return 0;
}
If val_to_check is declared const instead, the assertion can be folded away by the compiler.
I'm curious if it's possible to get a similar constant folding with a member variable of a class. For example, can I do something like:
class Test {
public:
Test(int val) : val_(val) {}
int some_func(int param) {
assert(val_ == 0);
return param*param+param;
}
private:
const int val_;
};
So val_ must be known when the class is defined, a-la:
Test my_test(0);
printf("Val: %i\n", my_test.some_func(rand()));
(I know these are contrived examples). It seems like it should be possible to fold the assertions away sometimes, but the simple examples I've tested don't seem to do it. The best I've gotten is moving the assertion code to the end of the function (when compiling w/ -O3)
In the class example you provided, there's no way for the compiler to assume the constant is zero because you have two runtime variables:
Your const int val_ is only constant for each instance of the class so it can never optimise the class's function code since it must cater for every case.
The example instantiation doesn't provide a literal constant, it provides the result of rand() which is variable. It may be possible for it to optimise it out if it knows the ONLY val_ ever being provided to all instances of that class is zero.
Have you tried providing a constant to the constructor to see if it optimises it out?
In C++, there is the notion of a "constant expression" (5.19). This is a literal expression, an arithmetic expression only involving constant expressions, or a value of a variable initialized statically with a constant expression. The compiler is able to determine the value of such an expression at compile time.
In your case, val_ is not a "constant expression", since it may have different values depending on the object it is a member of. For the out-of-line version of some_func, you probably agree that the compiler cannot know that it is a constant. For the inline version, it would be possible to determine the value of val_, assuming you also have the complete source code of all constructors analyzed. Whether the compiler is able to make this analysis is a quality-of-implementation issue - your compiler apparently is not able to.
val_ is const for the instance, not for all instances. If you actually want it to be the same for all instances, then you can make it static const and that would allow the compiler to optimize it out which is really what is happening in your first example with a global made const.
As a side note, your examples are subject to integer overflow.
-O2 seems to do the trick for me:
% cat foo.cxx
#include <cstdio>
#include <cstdlib>
#include <cassert>
class Test {
public:
Test(int val) : val_(val) {}
int some_func(int param) {
assert(val_ == 0);
return param*param+param;
}
private:
const int val_;
};
int main() {
Test my_test(0);
printf("Val: %d\n", my_test.some_func(rand()));
return 0;
}
% g++ -S foo.cxx && grep assert foo.s ; echo $?
.ascii "%s:%u: failed assertion `%s'\12\0"
0
% g++ -O2 -S foo.cxx && grep assert foo.s ; echo $?
1
If you want an assert that you're sure gets folded away, you might want to look up boost::static_assert.
Right now, I'm rather bothered by the basic notion of the design: you're allowing the user of the class to supply a value, but then asserting that it must be one particular value. If only one value is right, why have them supply it at all? Why not just use the right value and be done with it?
Keep in mind that the general idea of an assert is that its failure should NOT signal something like incorrect input. It should only be used to signal a fundamental problem with the program itself -- that there's faulty logic somewhere, or something on that order.
On the other hand, maybe you're dealing with a situation where different values are allowed, but you want to take different actions (or implement the same actions differently) for one particular value. To get the assert folded away, it's obviously going to have to be a compile-time constant.
That being the case, I'd consider creating a template, with that value as a non-type template parameter. Specialize the template for the value you want to implement specially. This gives roughly the effect you seem to want, but enforces the fact that the test for that value has to happen at compile time, not run time. Instead of writing run-time code and hoping the compiler's smart enough to handle it at compile time, you write a compile-time match explicitly.