Visual C++ constexpr Hints - c++

Visual C++ is notorious for ignoring constexpr function qualifiers unless absolutely required. Look at the following function:
constexpr int multiply(int l, int r) noexcept
{
return l * r;
}
According to the standard, Visual C++ is completely allowed to not evaluate the rvalue at compile-time:
auto three_times_four = multiply(3, 4);
The workaround I've been using is this ugly force:
constexpr auto constexpr_three_times_four = ;
auto not_constexpr_three_times_four = constexpr_three_times_four;
// use not_constexpr_three_times_four in non-constexpr contexts
// alternatively:
template<auto val>
inline constexpr auto ensure_constexpr = val;
auto not_constexpr_three_times_four = ensure_constexpr<multiply(3, 4)>;
Is there a way I can hint to the compiler that these things should be evaluated at compile-time?
I'm especially annoyed with the following:
namespace l
{
constexpr ::std::uint32_t operator""_crc32(const char * p, ::std::size_t const size) noexcept
{
return crc32(p);
}
}
//...
using namespace l;
search("foo"_crc32);//You don't want to evaluate this at runtime? too bad.
So, what can I do to hint the compiler in this case and avoid these ugly fixes?

There is no mechanism to "hint" to the compiler (any compiler) that a constexpr function "should" be called at compile-time. That's not what constexpr is for. It's not a tool for speeding up execution of code. It's a tool for allowing you to do computations that have to be done at compile-time.
C++20 allows functions to be designated consteval, which ensures that the function must be executed within a constant expression. But even that feature isn't for performance; it's there so that they can add new features of the language (like reflection values) that can only exist at compile time and cannot leak into runtime code.
C++20's constinit allows you to declare non-constant expression variables whose initializer is required to be a constant expression. That's the closest C++ gets to constexpr-as-a-performance-feature.
But otherwise, if the compiler's higher optimization levels aren't calling those functions at compile time, then that's how the compiler has chosen to implement the feature.

Related

Why does `auto` not adopt the constexpr'ness of its initializing expression?

Why doesn't defining a variable with auto keyword carry the constexpr'ness of the expression used to initialize it?
As an example, consider the following code:
#include <string_view>
constexpr std::string_view f() { return "hello"; }
static constexpr std::string_view g() {
constexpr auto x = f(); // (*)
return x.substr(1, 3);
}
int foo() { return g().length(); }
With GCC 10.2 and --std=c++20 -fsanitize=undefined -O3, this compiles into:
foo():
mov eax, 3
ret
But if we remove the constexpr on line (*), we would get a 27-line program with a bunch of pointers, a long string constant etc.
Notes:
I marked this question C++20, but I have no reason to believe this behavior is different from C++11's.
This question is not about the example, it is about the general behavior of auto w.r.t. constexprness. The example simply shows that that GCC does not treat x as constexpr if we don't explicitly tell it to.
auto is intended to enable type deduction, not a replacement for "everything useful you would have typed here". constexpr is not a part of an expression's type, and is thus ignored by auto (as opposed to const and volatile, which are part of an expression's type, and are deduced).
But if we remove the constexpr on line (*), we would get a 27-line program with a bunch of pointers, a long string constant etc.
That is a choice for your compiler. It has 100% of the information it needs to make that code go away. The fact that it didn't is not the C++ standard's concern.
This is a "quality of implementation" issue, not a standardization issue. If an implementation won't run as much of your code at compile-time as you desire, you can complain to them about it.
Remember: constexpr isn't meant to be a runtime optimization per-se. It's meant to allow you to write things that you otherwise couldn't write. Like std::get<g()>(some_tuple) or whatever. That code has to run at compile-time, since it's being used in a template parameter.
I'm not asking about some kind of deep deduction, only about the case of the function explicitly being constexpr.
Let's forget for a moment that auto is for type deduction and constexpr is not part of the type system. Let's focus instead on what if auto was supposed to deduce constexpr anyway. So what you want is for auto to only deduce constexpr if <expr> is specifically a function that is designated constexpr.
So let's look at some code:
auto x = constexpr_func();
auto y = constexpr_func() + 5;
auto z = constexpr_func() + constexpr_func();
auto w = constexpr_func_2() + constexpr_func_2();
Which of these variables are constexpr? If what you want is what we had, then x would be constexpr, but y would not. I personally would find this both surprising and annoying.
Worse, if we assume constexpr_func() returns an int, then z is also not constexpr. But if constexpr_func_2() returns a user-defined literal type that has a constexpr operator+, then w would be constexpr.
Isn't that all very weird? So I highly suspect that this is not what you really want.
What you really want is for auto x = <expr>; to deduce constexpr if constexpr auto x = <expr>; would be valid.
But really, that goes back to the original point. If you make a variable constexpr, that should mean you want it to be used in a place where being constexpr is required by some process. Given that fact, deducing constexpr makes no sense, because you should need it to be constexpr lest you get a compile error.

How to tell if expression is evaluated at compile time or runtime?

I have a rather big Map object and I want to have a separate list that has the keys sorted. This will be used in many other source files of my poject.
The question is about how do I know when a decalaration/definition is a compile time job. Where should I look to find if this is the case? I mean how to tell?
In the following example, is the list in the source file a compile time job or it happens at runtime?
Also, is there a way that I make the sorting operation at compile time?
// global.h
extern QMap<int, QString> G_MAP;
extern QList<int> G_MAP_SKEYS_SORTED;
// global.cpp
QMap<int, QString> G_MAP = { /* some hand filled (static) data */ };
QList<int> G_MAP_SKEYS_SORTED = G_MAP.keys();
// main.cpp
int mian() {
// Somewhere I do the sort
std::sort(G_ListRegistersSorted.begin(), G_ListRegistersSorted.end());
}
An expression is evaluated at compiletime if the result is assigned to a constexpr variable, used in a static_assert or noexcept statement, or used as a template parameter. This is called a constexpr context.
For example:
// Function which can calculate the fibbonacci sequence at compiletime
constexpr int fib(int n) {
if(n == 0 || n == 1) return n;
return fib(n - 1) + fib(n - 2);
}
int main() {
// This one is calculated at compiletime
constexpr int fib10_at_compiletime = fib(10);
// This one is calculated at runtime
// (unless the compiler was really aggressive when doing optimizations)
int fib10_at_runtime = fib(10);
}
In order to call a function or something at compiletime, it needs to be marked constexpr.
What can you do at compiletime?
C++11:
Declare variables (but not modify them)
Call other constexpr functions
Call constexpr constructors (and default ones)
Use carrays and std::array
Use static_asserts and stuff
typedef and using declarations
C++14 additions:
You can also use lambdas now
You can modify variables inside a constexpr function
you can have constexpr member functions that change member variables
you can pass references (the non-const kind) to constexpr functions
C++20 additions: (C++20 is coming out in 2020)
You can allocate memory now
You can call virtual functions now
You can have try-catch blocks
Is std::sort constexpr?
In order to use a function in a constexpr context, it must be marked constexpr (which comes with a set of restrictions on what you can do in the function; these are discussed below). In C++11, std::sort isn’t constexpr because it breaks those restrictions (and it won’t be constexpr until C++20).
However, if you’re allowed to use C++14, you can write your own sorting function that works at compile time.
Full overview: https://en.cppreference.com/w/cpp/language/constexpr
Also, is there a way that I make the sorting operation at compile time?
Short answer: no.
Long answer.
No because std::sort() is constexpr only from C++20 (you tagged C++11), because a void function (std::sort()) can't be constexpr in C++11, because QMap and QList aren't constexpr classes (if I'm not wrong), because you haven't declared GMAP and other object involved as constexpr, etc.
But, supposing to have a MyMap class defined constexpr, a MyList class declared constexpr, a MySort() function defined constexpr, you could write something similar (starting from C++14 because in C++11 you can't write a so complex constexpr function)
constexpr MyList foo ()
{
MyMap mm { /* some values */ };
MyList ml { ml.keys() };
MySort(ml.begin(), ml.end());
return ml;
}
// ...
constexpr auto ml_final { foo() };
Observe that ml_final is declared constexpr.
This is necessary to impose (pre C++20) the compiler to initialize the value compile-time, if possible, or give a compilation error, if impossible.

Branching on constexpr evaluation / overloading on constexpr

The setup:
I have a function that uses SIMD intrinsics and would like to use it inside some constexpr functions.
For that, I need to make it constexpr. However, the SIMD intrinsics are not marked constexpr, and the constant evaluator of the compiler cannot handle them.
I tried replacing the SIMD intrinsics with a C++ constexpr implementation that does the same thing. The function became 3.5x slower at run-time, but I was able to use it at compile-time (yay?).
The problem:
How can I use this function inside constant expressions without slowing down my program at run-time?
Some ideas:
Adding support for constant evaluating all SIMD intrinsics to the compiler constant expression evaluator, for all compilers: probably the right solution, but an impossible titanic task.
More pragmatic solutions would be to either:
overload a function depending on whether it is being executed inside a constant expression (that is, provide a constexpr, and a non-constexpr version).
or, somehow branch inside a constexpr function between the constexpr and run-time implementation (that is, detect in a branch whether the function is being executed inside a constant expression).
Anyhow, I am open to any suggestion that solves my problem.
Hints:
#RMartinhoFernandes suggested in the Lounge to use __builtin_constant_p to detect whether the function arguments are all constant expressions, in which case the compiler would hopefully be at least attempting to evaluate the function at compile-time.
Failed attempts:
#Jarod42 made the straight forward suggestion of just using two independent functions. I would briefly like to point out why this cannot work because it is not trivial. This solution assumes that at the call-site it is known whether the function will be constexpr evaluated or not. But this is not the case. Consider a constexpr function calling mine, which version of my function should it pick? It must pick the constexpr one in order for it to compile, but that "outer" constexpr function could still be evaluated at run-time. In that case, it would use the "slow" compile-time implementation, and hence, this approach does not solve the problem.
I would do it like this
constexpr int doit(int input, bool inconst = false) {
return inconst ? doitconsty(input) : doitfast(input);
}
If the call to doit is inside of a constexpr function that can be called to perform something either at runtime or at compile time, just forward the flag
constexpr int f(int n, bool inconst = false) {
/* ... */
int importantInt = doit(n / 42, inconst);
/* ... */
return magicResult;
}
Any constexpr evaluation has something where it starts, if I'm not mistaken. Pass the inconst there
enum foo { bar = f(256, true) }
If you are in the runtime world, just call f like anything else
int main() { std::cout << "test-case: " << f(256); }
It should be noted that this does not work for operators, because you can't add the boolean parameter there. Instead, you could pass the value in some different way, if that's fine for you (for primitive values like int and bool, we could not overload the operator either).
template<typename T>
struct maybe_const_value {
T t;
bool isconst;
};
enum foo { bar = maybe_const_value{256, true} % magicTransform };
int main() { return maybe_const_value{265} % magicTransform; }
The operator function can then check input.isconst and use input.t as the actual value.

Is constexpr a "hint" (like inline) or "a binding request" to the compiler?

Is constexpr an indicator for the compiler or does it mandate a behaviour ?
The example at hand is the following :
template<typename T>
std::size_t constexpr getID() { return typeid(T).hash_code(); }
hash_code is a runtime constant, yet this snippet would compile even though a compile time evaluation is requested with constexpr. Only after the return value is used where a compile time constant is expected, would we get noticed that this is not usable as a constexpr function.
So is constexpr a "hint" (much like the inline keyword) or "a binding request" to the compiler ?
Is constexpr a “hint” (like inline) or “a binding request” to the compiler?
It is neither. Forget about when it is evaluated. Everything (with a few minor exceptions, notably involving volatile) is evaluated whenever the compiler deems it necessary to produce the behaviour of the C++ abstract machine. There isn't much else to say about when things are evaluated.
The compiler is free to produce code that evaluates what would be constant expressions at runtime if that doesn't produce a different behaviour. It is free to produce code that evaluates things not marked constexpr at compile-time if it has the smarts.
If not about compile-time vs runtime, what is constexpr about, then?
constexpr allows things to be treated as constant expressions. Anything marked constexpr must have the possibility of producing a constant expression in some way.
In the case of functions, they can be able to produce constant expressions with some arguments but not others. But as long as there is some set of arguments that can result in a constant expression, a function can be marked constexpr. If such a set of arguments is used in a function call, that expression is a constant expression. Does that mean it is evaluated at compile-time? See above. It's evaluated when the compiler deems appropriate. The only thing it means is that you can use it in a context requiring a constant expression.
For variables, either they are constant expressions or not. They have no arguments, so if constexpr they always have to be initialised with constant expressions.
TL;DR: constexpr is about tagging things as being usable in constant expressions, not about deciding when to evaluate them.
With that out of the way, it appears your function template is ill-formed. There is no set of arguments that could result in a constant expression. The standard doesn't require a diagnostic for this, though.
From the C++11 Wiki page:
If a constexpr function or constructor is called with arguments which
aren't constant expressions, the call behaves as if the function were
not constexpr, and the resulting value is not a constant expression.
Likewise, if the expression in the return statement of a constexpr
function does not evaluate to a constant expression for a particular
invocation, the result is not a constant expression.
The constexpr specifier thus expresses the possibility to evaluate something at compile time and is subject to some restrictions when used.
For your particular snippet it seems to me that the C++11 constraint:
exactly one return statement that contains only literal values,
constexpr variables and functions
is not fulfilled, as hash_code is defined to be:
size_t hash_code() const;
In this case the standard draft n3242 says:
For a constexpr function, if no function argument values exist such
that the function invocation substitution would produce a constant
expression (5.19), the program is ill-formed; no diagnostic required.
I believe your example fits here.
constexpr functions can be used to evaluate compile time constants. So it is possible to use it like:
constexpr int func(int a) { return a+2; }
char x[func(10)];
If func is called during runtime, the compiler can evaluate this expression before if possible. But that is not a must but normally done if the input is also const.
It is also important to have constexpr constructors. This is the only chance to get non POD classes constexpr objects.
class Point
{
private:
int x;
int y;
public:
constexpr Point( int _x, int _y) : x(_x), y(_y) {}
constexpr int GetX() const { return x; }
};
constexpr Point p{1,2};
int main()
{
char i[p.GetX()];
return 0;
}
The complete answer to your question has two aspects:
A constexpr function can only be evaluated at compile-time when all
arguments can be evaluated at compile-time. It can still be used as
a normal function which is evaluated at runtime.
An constexpr variable must be initialized with a value evaluated at compile-time.
The compiler has to raise an error if it cannot do this.
You could assign the hash code to a constexpr variable and then get a compiler output:
#include <typeinfo>
#include <array>
template<typename T>
std::size_t constexpr getID() {
return []() {constexpr size_t id = typeid(T).hash_code(); return id;}(); }
int main() {
// both statement generate compiler errors
//std::array<int, typeid(int).hash_code()> a;
//constexpr size_t y = typeid(int).hash_code();
size_t x = getID<int>();
}

single expression helper for compile-time enforced constexpr function evaluation possible?

#cyberpunk_ is trying to achieve something and made some questions about it but all the chase boils down to this:
Is it possible to build a tool to enforce compile-time evaluation of a constexpr function?
int f(int i) {return i;}
constexpr int g(int i) {return i;}
int main()
{
f(at_compilation(g, 0));
int x = at_compilation(g, 1);
constexpr int y = at_compilation(g, 2);
}
In all situations, at_compilation enforce compilation-time evaluation of g.
at_compilation doesn't need to be in this form.
Requirements
Allow any (numerical native) literal type as input for the constexpr function.
this could also be hardcoded based on the function arguments types.
Allow any (numerical native) literal type as output, which is the result of the constexpr function call.
this could also be hardcoded based on the function return type.
Desirables
Reduced macro usage but don't be afraid of using.
Be general (not type hardcoded).
Support any literal type. At last any numerical native literal type is a requirement.
Related Questions:
When does a constexpr function get evaluated at compile time?
Forcing a constant expression to be evaluated during compile-time?
Passing any function as a template parameter?
Where in the C++11 standard does it specify when a constexpr function can be evaluated during translation?
Answers with relevant code samples:
1
2
3 (this one has an illustrative AT_COMPILATION macro)
All the code samples have limitations regarding the requirements.
A clear explanation for how this is unfeasible in C++ is also a good answer.
I suspect it's impossible based on #K-ballo / #Herb Sutter answer which states "and the result is used in a constant expression as well". This was not part of my former conception about constexpr functions, I firstly thought that just passing literals (or other compile-time input) as arguments would suffice to guarantee (by standard) it to be evaluated at compilation-time.
It's already assumed constexpr function's purpose is that they can fit in constant expression situations when necessary, like in array bounds. That's OK. Given that, this question is about a hack on using them just as a tool for compile time calculation. Whether it's a good or bad thing to do should not matter.
I believe that it's impossible because the compiler is only required to compute values that are used at compile-time, and there is no generic expression that can use every part of a value of class type. Computations that initialize private members might even be impossible to force, as you would depend on a public constexpr member function to use the result.
If you could access the object representation by
static_cast< char const * >( static_cast< void const * >( & const_value ) )
then it would be possible to checksum the result of the computation (and use the result as an integral constant expression), forcing the compiler to perform every calculation that isn't moot. But the cast from void * to char * is disallowed in a constant-expression, and likewise attempting to accomplish the same with a union. Even if it were allowed, if the constructor left one byte uninitialized, using an uninitialized value is also forbidden in a constant-expression.
So, even if C++ had better tools for introspection, it would still be impossible to recover the work performed by a constexpr function in order to artificially use some members but not others.
Just to be clear (even if it repeats the question), there's no reason to want this. The language already requires a check that everything can be computed at compile time, if needed, and the only effect of forcing the compiler to non-lazily compute pure values would be to make it slower and use more memory.
Edit (question was radically altered)
If you have several functions returning scalar type, and want to ensure that some of them work as constant expressions under certain arguments, then write test cases using static_assert.
constexpr int g(int i) {return i;}
int i = 5;
static_assert( g( 3 ) == 0, "failure 1" );
static_assert( g( i ) == 5, "failure 2" );
If you don't want to fix the result values, then discard them. (Unfortunately, GCC may optimize out the non-constant part of such an expression, so you might need to do something more baroque on that platform.
static_assert( g( i ) == 5 || true, "failure only if not constexpr" );
As for encapsulating this into a macro, the other linked questions seem to address a lot. If you want to expand one of those answers or to fix a particular bug, it would be better to explain the bug rather than ask us to read so much literature and start from scratch.
Thanks to C++17 (lambda constexpr, auto template parameter, inline as valid template non-type value) we now have a solution:
//implementation
#include <utility>
template<auto X>
using constant = std::integral_constant<decltype(X), X>;
template<class T>
constexpr auto to_constant(T f) //should use && but clang has a bug that would make +f fail
{
constexpr auto ptr = +f; //uses conversion operator to function pointer
return constant<ptr>{}; //not yet implemented for gcc ("no linkage"), working with clang
}
#define constexpr_arg(...) to_constant([]{ return __VA_ARGS__; })
//userland
template<auto Func>
constexpr void func(constant<Func>)
{
constexpr decltype(auto) x = Func();
static_assert(x == 3.14);
}
int main()
{
func(constexpr_arg(3.14));
}
proof it's working : https://godbolt.org/g/vWbyjE
Also this version doesn't work for all cases (mainly if the argument of the macro uses non-constexpr values but still produce a constexpr result).
For such uses cases : https://godbolt.org/g/DRZ5JM
For a gcc version (so portable for now):
//implementation
template<class T>
struct constant
{
static constexpr decltype(auto) value = T::getPtr()();
};
template<class T>
constexpr auto to_constant(T&& f) //remove the && if you want to be also compatible with clang
{
constexpr auto ptr = +f; //uses conversion operator to function pointer
struct A
{
static constexpr auto getPtr() { return ptr; }
};
return constant<A>{};
}
#define constexpr_arg(...) to_constant([]{ return __VA_ARGS__; })
//userland
template<class Constant>
constexpr void func(Constant&&)
{
static_assert(Constant::value == 3.14);
}
int main()
{
func(constexpr_arg(3.14));
}
https://godbolt.org/g/LBCYfi
Use std::integral_constant:
int x = std::integral_constant<int, g(0)>::value;
f(std::integral_constant<int, g(1)>::value);
This code will not compile if g(n) is not evaluated at compile-time.