Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

constexpr - why just a return statement?

Tags:

c++

c++11

A constexpr function must just consist of a return statement and every argument should be known at compile time:

// constexpr functions use recursion rather than iteration
constexpr int factorial(int n)
{
    return n <= 1 ? 1 : (n * factorial(n-1));
}

Why just the return statement? I mean, why this is wrong?

// constexpr functions use recursion rather than iteration
constexpr int factorial(int n)
{
    int a = 222; //another variable
    return n <= 1 ? 1 : (n * factorial(n-1));
}
like image 710
Marco A. Avatar asked Jun 08 '13 22:06

Marco A.


People also ask

Why does constexpr need to be static?

A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later.

Can a function return constexpr?

Unlike const , constexpr can also be applied to functions and class constructors. constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time.

When to use #define vs constexpr?

#define directives create macro substitution, while constexpr variables are special type of variables. They literally have nothing in common beside the fact that before constexpr (or even const ) variables were available, macros were sometimes used when currently constexpr variable can be used.

Should I use const with constexpr?

const can only be used with non-static member functions whereas constexpr can be used with member and non-member functions, even with constructors but with condition that argument and return type must be of literal types.


2 Answers

Why:

Because constexpr is a fairly new and radical concept in C++11 and it is difficult to transition a major language standard to something completely new. Conservatism rules.

For C++1y (currently targeted at C++14), your example is legal. Tip of trunk clang already implements it under the -std=c++1y flag.

like image 66
Howard Hinnant Avatar answered Oct 21 '22 02:10

Howard Hinnant


It simplifies the implementation, as Andy Prowl says. That possibly answers "Why", but it doesn't say how it does that.

A function with only a return value, and more specifically one without local variables, is a special situation for a compiler. This function is now comprised of a single expression: the function's AST needs only to have a single root. That lack of variables means this expression can be evaluated without a full-blown virtual machine to process it, rather a simple tree expression evaluator can be used. For various reasons the compiler probably already has such an evaluator, or could create one relatively easily (it becomes a tree simplification pass).

Knowing that only constexpr is used inside the expression also provides a key simplification. This guarantees that each vertex in the function AST has the same properties, even if it is a function call. The entire constexpr mechanism is then a generalized form of const-folding. And though it isn't always done at this high level in the compiler, it ensures it can be implemented without a huge effort (compared to a full VM).

Back to the "why" question. The restriction is driven primarily by resource limitations on the vendors. This feature, as specified, is not a huge effort and thus the vendors can actually implement it in a reasonable period of time. If there were no such restrictions, in particular allowing local variables, it greatly increases the amount of work needed. From the user's perspective (us, the programmers), the restrictions are however entirely arbitrary.

like image 30
edA-qa mort-ora-y Avatar answered Oct 21 '22 02:10

edA-qa mort-ora-y