Why can't I use constexpr with lambda function? - c++

I need an explanation for this. How does lambda differ from others function to it don't be allowed? Is this a nonsense to be not part of C++ standard? for example, I wanted to write a "nested" function in C++ but like it isn't possible to do directly I do use lambda instead of. This function does a very small job: take a single int parameter and multiply with some values and returns. This values are locals to where lambda function is defined and all them are constexpr and know at run-time for this reason I do want to let the compiler put a const value instead of call the function. It's very often used function (that's why I write this as function) and I don't want this beging computed at run-time.

It is because the standard list lambda as non constant expression : "5.19 Constant expressions" … "is a core constant expression unless it involves one of the following as a potentially evaluated subexpression" … "— a lambda-expression (5.1.2);"
That is enough for any compiler to reject constexpr function with a lambda involved.

Related

How to determine if a parameter is a constexpr in compile-time

I have a compile-time string class that helps programs compute various relevant things at compile time, such as hash results and a quick lookup table for find, which is constructed like this:
"hello"_constexpr_str;
Also, my string class supports construction from this type, which allows for fast hash and fast find and avoids unnecessary data copying, like this.
defs::string string = "hello"_constexpr_str;
Of course, my string class also supports building from const char_T*
Now here's the problem!
I want to use the constexpr method automatically when my string class is constructed with compile-time constants like string("hell word!") rather than ugly but strong string("hell word!"_constexpr_str)
In other words, I want string("hell word!") to automatically become string("hell word!"_constexpr_str) in compile-time to calculate the information about the constant string and put it in constant state storage, so that all my string class has to do is hold a pointer to constexpr_str_t
//Draft Code
#if defined(__cpp_if_consteval)
#define if_in_consteval if consteval
#else
#define if_in_consteval if constexpr(0)
#endif
constexpr string_t(const constexpr_str_t&str)noexcept;//save a pointer to constexpr_str_t
string_t(const char_T* str)noexcept{
if_in_consteval{
constexpr constexpr_str_t constexpr_str(str);
construct[this](constexpr_str);
}
else{
construct[this](string_view_t(str));
}
}
What do I do to achieve this?
If I understood your question now after the discussion in the comments correctly, you have a operator""_constexpr_str which is marked consteval and returns a string-view-like type constexpr_str_t with some additional information attached based on the contents of the string.
You then have a function taking an (ordinary) string literal as argument with overloads taking either constexpr_str_t or const char*. You basically want the const char* overload to only be chosen when the argument is not a constant expression. Otherwise the constexpr_str_t overload should be chosen and constructed at compile-time (i.e. via consteval) so that the extra information can be attached at compile-time.
This cannot work however, because it is impossible to overload on consteval. Whether or not a consteval function is called depends only on the type of the argument. It is not possible to distinguish between constant expression arguments and non-constant expression arguments.
Trying to determine whether a function argument is a constant expression inside a function is also impossible. Functions are compiled individually. They are not compiled twice depending on whether or not the argument is a constant expression.
The only thing possible is to change behavior based on whether the whole expression that the function call is used in is a context requiring a constant expression. That is what if consteval is for. But if you are making a decision based on such a scenario, you don't need
constexpr constexpr_str_t constexpr_str(str);
You can simply do the calculation for the additional properties of the string there as if at runtime and mark the function constexpr. If used in a context requiring a constant expression it will be evaluated at compile-time.
If you want to enforce this even if the call doesn't happen in a context requiring a constant expression, then it is impossible.
You can however write a macro which tests whether an expression is a constant expression and then conditionally calls either a consteval function or a non-consteval function. It is just impossible through a function call.
You can use the C++20 std::is_constant_evaluated() function found in the <type_traits> header. It detects whether a function call occurs within a constant-evaluated context.

C++ Construct to check whether a local expression is not a constant expression

I'm looking for some construct that can detect whether a local expression is a constant expression, or whether it's not, that can be used in a static_assert declaration.
In code:
int main()
{
constexpr int i = 1;
if constexpr(i) {}
static_assert(is_constexpr(i));
int j = 1;
//if constexpr(j) {} // error: 'j' is not usable in a constant expression
static_assert(!is_constexpr(j));
}
The is_constexpr here can be a macro, a class (then probably with other syntax), or a function. How to make is_constexpr(i) return true/true_type and, conversely, is_constexpr(j) return false/false_type?
I tried a lot of the solutions available here on SO (also using old-school SFINAE) without success. I can edit in the links and my failed attempts if required.
Playground on godbolt here
The problem is that parameters (like t) are not constant expressions. For example, we cannot use t as a template non-type parameter, or as a size of a built-in array.
This means that some expression say some_expr( t ) that contains(involves) the subexpression t is itself not a constant expression, either.
Can is_constexpr be a function?
The simple fact that you write is_constexpr(i) means that you're looking for a function of type bool(auto); but you also want to be able to pass it constexpr arguments or non-constexpr arguments, so for sure it can't be consteval otherwise it would error when called in the latter scenario; so you can at most make it constexpr. However, there's no such a thing (yet?) as a constexpr function parameter, so as soon as you pass something to that constexpr function you have no way to detect whether or not the argument was a constant expression at the call site.
Can is_constexpr be a meta-function?
The other opportunity would be to use a metafunction, but how would you expect to call it? If you expect is_constexpr<i>, i.e. passing the entity you are querying as a template argument, that would be clearly only possible if i is constexpr; if you go for is_constexpr<decltype(x)>, you are expecting that decltype(x) contains some info about the constexpr-ness of x, but that's not the case, as constexpr/consteval are not part of the type of an expression.
Do you really need it?
This, I believe, means that whenever you ask whether an expression is a constant expression, you can always find the answer by looking at the code before that expression, and that answer will not depend on any boolean condition, not even a constexpr condition.
In other words, I believe (and happy to be proved wrong), there's no way for an expression appearing in a C++ program to be constexpr or not in the same line of code depending on the path that leads there.
Do we really have a usecase?
I agree that this is likely an XY problem.
So I challenge you to write an example where a given C++ expression of your choice appearing at a certain line of code is constexpr across one branch of execution and non-constexpr across another branch. And the branches can also be compile-time (well, given your question, you were not asking about non-compile-time branching, so in the previous sentence you can can also be are).

Any reason not to use global lambdas?

We had a function that used a non-capturing lambda internal to itself, e.g.:
void foo() {
auto bar = [](int a, int b){ return a + b; }
// code using bar(x,y) a bunch of times
}
Now the functionality implemented by the lambda became needed elsewhere, so I am going to lift the lambda out of foo() into the global/namespace scope. I can either leave it as a lambda, making it a copy-paste option, or change it to a proper function:
auto bar = [](int a, int b){ return a + b; } // option 1
int bar(int a, int b){ return a + b; } // option 2
void foo() {
// code using bar(x,y) a bunch of times
}
Changing it to a proper function is trivial, but it made me wonder if there is some reason not to leave it as a lambda? Is there any reason not to just use lambdas everywhere instead of "regular" global functions?
There's one very important reason not to use global lambdas: because it's not normal.
C++'s regular function syntax has been around since the days of C. Programmers have known for decades what said syntax means and how they work (though admittedly that whole function-to-pointer decay thing sometimes bites even seasoned programmers). If a C++ programmer of any skill level beyond "utter newbie" sees a function definition, they know what they're getting.
A global lambda is a different beast altogether. It has different behavior from a regular function. Lambdas are objects, while functions are not. They have a type, but that type is distinct from the type of their function. And so forth.
So now, you've raised the bar in communicating with other programmers. A C++ programmer needs to understand lambdas if they're going to understand what this function is doing. And yes, this is 2019, so a decent C++ programmer should have an idea what a lambda looks like. But it is still a higher bar.
And even if they understand it, the question on that programmer's mind will be... why did the writer of this code write it that way? And if you don't have a good answer for that question (for example, because you explicitly want to forbid overloading and ADL, as in Ranges customization points), then you should use the common mechanism.
Prefer expected solutions to novel ones where appropriate. Use the least complicated method of getting your point across.
I can think of a few reasons you'd want to avoid global lambdas as drop-in replacements for regular functions:
regular functions can be overloaded; lambdas cannot (there are techniques to simulate this, however)
Despite the fact that they are function-like, even a non-capturing lambda like this will occupy memory (generally 1 byte for non-capturing).
as pointed out in the comments, modern compilers will optimize this storage away under the as-if rule
"Why shouldn't I use lambdas to replace stateful functors (classes)?"
classes simply have fewer restrictions than lambdas and should therefore be the first thing you reach for
(public/private data, overloading, helper methods, etc.)
if the lambda has state, then it is all the more difficult to reason about when it becomes global.
We should prefer to create an instance of a class at the narrowest possible scope
it's already difficult to convert a non-capturing lambda into a function pointer, and it is impossible for a lambda that specifies anything in its capture.
classes give us a straightforward way to create function pointers, and they're also what many programmers are more comfortable with
Lambdas with any capture cannot be default-constructed (in C++20. Previously there was no default constructor in any case)
Is there any reason not to just use lambdas everywhere instead of "regular" global functions?
A problem of a certain level of complexity requires a solution of at least the same complexity. But if there is a less complex solution for the same problem, then there is really no justification for using the more complex one. Why introduce complexity you don't need?
Between a lambda and a function, a function is simply the less complex kind of entity of the two. You don't have to justify not using a lambda. You have to justify using one. A lambda expression introduces a closure type, which is an unnamed class type with all the usual special member functions, a function call operator, and, in this case, an implicit conversion operator to function pointer, and creates an object of that type. Copy-initializing a global variable from a lambda expression simply does a lot more than just defining a function. It defines a class type with six implicitly-declared functions, defines two more operator functions, and creates an object. The compiler has to do a lot more. If you don't need any of the features of a lambda, then don't use a lambda…
After asking, I thought of a reason to not do this: Since these are variables, they are prone to Static Initialization Order Fiasco (https://isocpp.org/wiki/faq/ctors#static-init-order), which could cause bugs down the line.
if there is some reason not to leave it as a lambda? Is there any reason not to just use lambdas everywhere instead of "regular" global functions?
We used to use functions instead of global functor, so it breaks the coherency and the Principle of least astonishment.
The main differences are:
functions can be overloaded, whereas functors cannot.
functions can be found with ADL, not functors.
Lambdas are anonymous functions.
If you are using a named lambda, it means you are basically using a named anonymous function. To avoid this oxymoron, you might as well use a function.

How do to pass variable number of arguments to a function in c++ with no named parameters

I need to write a function which takes a variable number of arguements, its essentially a wrapper around a snprintf like function. I understand how to do this in general as shown in Passing variable number of arguments around.
How ever it appears that, atleast in C, we are required to pass one named parameter to the function before the variable arguments start( Why is void f(...) not allowed in C? ).
However the answers to the same questions say this is easily possible in C++. I was wondering how to achieve this, especially since the method for handling vararg functions seems to be the same as C(va_start, etc). Or are they referring to variadic templates?
So basically is it possible to write a variadic function with no named arguements, as shown below, and if so, how?
void f(...){
...
}
p.s. I would like to do this with c++03 if possible.
While C++ language allows writing functions whose parameter list consist only of ..., the language provides no means for accessing the arguments in functions declared with (...) parameter list.
Basically such functions in C++ exist for their behavior in overload resolution (... parameters match any parameter type). The body of such function will not have access to the arguments. If you see no uses for such functions, just don't use them.
Such functions are often used in non-executed context in some well-known template meta-programming techniques, in which case they don't even have to be defined - a mere declaration is sufficient.

inline vs. constexpr?

With the new C++11 standard, when should I use the inline keyword over the constexpr keyword? Does the constexpr keyword offer any additional optimization over inline, or does it merely assert that things must be computed at compile-time?
Why does constexpr work on the GCC in some cases where the call is not constant, such as calling foo(x) on a non-constexpr variable? Is this a bug in the GCC or is it actually part of the standard?
Asserting that something can be computed at compile-time is a pretty strong kind of optimization.
Inlining merely removes a function call, by copy/pasting the function body into the call site. The function body still has to be executed, you just save the overhead of a function call.
But if you make the same code be evaluated at compile-time, it is free at runtime.
But neither inline nor constexpr are primarily about optimization. inline's main purpose is to suppress the one-definition-rule, so that functions can be defined in headers (which is useful for templates, and incidentally, also makes the inlining optimization easier)
And constexpr is there because it is useful in metaprogramming, and incidentally, it may help the compiler better optimize the code, by moving more computations to compile-time.
To quote wikipedia:
C++0x will introduce the keyword constexpr, which allows the user to
guarantee that a function or object constructor is a compile-time
constant.
Mark functions inline if they are super short. Mark functions as constexpr if the results are required at compile time. (Template parameters or array sizes). I believe a function can be both if needed.
A constant expression function or constructor can be called with
non-constexpr parameters. Just as a constexpr integer literal can be
assigned to a non-constexpr variable, so too can a constexpr function
be called with non-constexpr parameters, and the results stored in
non-constexpr variables. The keyword only allows for the possibility
of compile-time constancy when all members of an expression are
constexpr.
So, GCC is not incorrect in this.
While inline says to the compiler "This function is used somewhere in this translation unit and is not public to other object files", it is likely that the compiler inserts the body of the function into the caller. constexpr functions say to the compiler "This function has no side effects and does not depend on preconditions other than the parameter itsself."
constexpr variables just say "This variable does not change and its data can be included into the code.". However it makes a difference if you define a constexpr variable in a function static or nonstatic, eg. if a constexpr array is nonstatic, gcc just moves the data with hardcoded mov-instructions onto the stack, while static constexpr just stores the data in the .text-section.
Lambda expressions without capture assigned to a variable can be constexpr other than with capture, because without they need no memory to save the capture and they work like an empty class with overloaded operator() (but they can even be casted to plain function pointers with a simple unary plus: +[]{}).