C++ constexpr keyword placement - c++

I have recently started using more C++11 features in my code and I have been wondering if the placement of the constexpr keyword makes difference whether it is before or after the constant's type.
Style 1:
constexpr int FOO = 1;
constexpr auto BAR = "bar";
Style 2:
int constexpr FOO = 1;
auto constexpr BAR = "bar";
Style 2 is the way I prefer to place the const keyword and placing constexpr the same way would bring some consistency to the code. However, is that considered bad practice or is there something else wrong with style 2 because I don't really see anyone writing it like that.

It's a specifier, like long, short, unsigned, etc. They can all be moved around. For example, the following are two equivalent and valid declarations:
int long const long unsigned constexpr foo = 5;
constexpr const unsigned long long int foo = 5;
By convention, though, constexpr would appear before the type name. It can confuse others if you put it after, but it is technically valid. Since constexpr serves a different purpose than const, I don't see the same benefit in putting it to the right. For example, you can't do int constexpr * constexpr foo. In fact, int constexpr * foo will not allow you to reassign foo, rather than apply to what foo points to, so putting it to the right can be misleading if you expect the same kind of semantics as const.
To summarize:
int constexpr foo = 0; // valid
int constexpr * constexpr foo = nullptr; // invalid
int* constexpr foo = nullptr; // invalid
int constexpr * foo = nullptr; // valid
constexpr int* foo = nullptr; // valid and same as previous

msdn defines the syntax as:
constexpr literal-type identifier = constant-expression;constexpr literal-type identifier { constant-expression };constexpr literal-type identifier(params );constexpr ctor (params);
Which says that you should use it on the left.
Edit:
New specifier The keyword constexpr is a declaration specifier; modify the
grammar in [ISO03, §7.1] as follows:
1 The specifiers that can be used in a declaration are
decl-specifier:
storage-class-specifier
type-specifier
function-specifier
friend
typedef
constexpr
An explanation is given for this specifiers here.
To sum up #chris' answer is right :)

Related

Is declaring variables as const redundant after constexpr was added to the language?

As the keyword constexpr implies const and it can also be calculated at compile time, does it mean that now declaring variables as const doesn't make sense and we should always declare them as constexpr?
and it can also be calculated at compile time, does it mean that now declaring variables as const doesn't make sense and we should always declare them as constexpr?
And must be calculated at compile time (ignoring the as-if rule).
So you can't declare constexpr a variable initialized with a run-time known value. But you can declare it const.
For example: you can't declare bar constexpr
int foo;
std::cin >> foo;
constexpr int bar = foo; // compilation error
but you can declare it const
int foo;
std::cin >> foo;
const int bar = foo; // compile
No, not at all.
constexpr means "constant expression", as in [possibly] statically-known, as in "[possibly] known at compile time".
const means "cannot be changed after initialisation".
These are completely separate concepts. A const object can be initialised with a runtime value, for example.
constexpr can imply const, but const certainly does not imply constexpr.
(I think constexpr is a very confusing name, due to this.)
Adding to #max66 answer: constexpr can only replace a top-level const. It can never replace pointer-to-const or const reference. So, sometimes constexpr and const can be used in the same declaration. E.g.
const char* const s = "Hello";
can be replaced with:
constexpr const char* s = "Hello";

static member declared const but initialized as constexpr

consider a class with a constant member:
class foo {
public:
const static int N;
};
foo::N needs to initialized:
constexpr int foo::N = 5;
and note how using the constexpr qualifier instead of const here seems like a mistake.
but GCC, Clang and MSVC all compile just fine!
is there something in the language that allows changing qualifiers here?
is it an error overlooked by all three compilers?
Clang even allows both qualifier versions simultaneously:
constexpr int foo::N = 3;
const int foo::N = 5;
int main(){
return foo::N; //returns 3
}
what's going on?
Since obviously the value of a variable that has been declared but not defined cannot be used in a constant expression, constexpr pertains only to the definition of a variable. (Of course, if the variable is inline, perhaps because of being a static member declared constexpr, every definition must have constexpr.) It implies const (on the variable itself: constexpr char* is char *const, not const char*), so you haven’t changed the variable’s type. This is no different from
// foo.hpp
extern const int x;
// foo.cpp
constexpr int x=2;
which is perhaps less surprising.
So everything is fine! The variable’s value can be used in constant expressions only in the translation unit that contains the definition, but that’s no surprise, and could easily be construed as a feature for modularity. Clang is buggy to allow two definitions: presumably it’s trying to ignore the (deprecated, as of C++17) out-of-class definition for a constexpr static data member defined in the class.

Which should I prefer for a constant within a function: constexpr const or enum?

I'm used to definition my constants with enum { my_const = 123; }, since in classes, using static constexpr requires some code outside of the class definition (see this question). But - what about in function bodies? Lately I've been noticing people just having constexpr variables in their functions (not even bothering to const them actually), and I was wondering whether I'm a fool who's behind the times with my
int foo(int x)
{
enum : int { bar = 456 };
return x + bar;
}
So, my question is: Is there any benefit to using enum's within function bodies rather than constexpr variables?
You can accidentally or on purpose force ODR-existence of bar if it was a constexpr int bar = 456;, this is not possible with enum : int { bar = 456 };.
This may or may not be an advantage on either side.
For example
int baz(int const* ptr ) {
if (ptr) return 7; return -1;
}
int foo(int x)
{
// enum : int { bar = 456 };
constexpr int bar = 456;
return x + baz(&bar);
}
the enum version doesn't compile, the constexpr int one does. A constexpr int can be an lvalue, an enumerator (one of the listed enum constants) cannot.
The enum values aren't actually an int, while the constexpr int is actually an int. This may matter if you pass it to
template<class T>
void test(T) {
static_assert(std::is_same<T,int>::value);
}
one will pass the test; the other will not.
Again, this could be an advantage, a disadvantage, or a meaningless quirk depending on how you are using the token.
A one-liner based on #Yakk's (but this is my own take):
using enum-based constants may be necessary if you cannot allow your constant to exist as a "variable" at run time . With an enum, regardless of what you do - it will have no address and no memory space taken up (and not only because of compiler optimizations which may or may not occur).
In other cases there doesn't seem to be a compelling reason to prefer one over the other.

How is in-class static const initialization of float different from int in C++?

I have a class with static const members that I'm initializing inside the class declaration:
#include <iostream>
class Foo
{
public:
static const int i = 9;
static const float f = 2.9999;
};
int main()
{
std::cout << Foo::i << std::endl;
std::cout << Foo::f << std::endl;
return 0;
}
When compiled with GCC 4.8.2 with option --std=c++11, it gives this compile error:
foo.cpp:7:32: error: ‘constexpr’ needed for in-class initialization of static data member ‘const float Foo::f’ of non-integral type [-fpermissive]
static const float f = 2.9999;
^
As the message indicates, the error goes away if the line is changed to static constexpr float f = 2.9999;.
Why should the in-class static const initialization of a floating-point variable be any different from a integral variable? Aren't they both just a value of certain size (number of bytes) that is copied over (like a macro) or referred to using a pointer?
Some older answers to similar (not the same) questions on SO indicate that this is because floating point expressions might give different results between the compiled machine and the execution machine (assuming a cross-compilation scenario).
However:
the above code assigns a value directly, there is no arithmetic operation that needs to be performed to compute a value
there might be different results for integral expressions too since its underflow and overflow results are not unambiguously defined across different architectures.
Finally, what magic does constexpr do here that const does not? Why doesn't the language just do what constexpr does when const is used? I mean, why another keyword when the following statements work fine as C++ code outside a class anyway:
const int i = 9;
const float f = 2.9999;
It's just a limitation of the language, and one that has been addressed by the introduction of generalized constant expressions.
Since the original C++, only static class member constants of integral type can be initialized inline; this is the is same type restriction as for non-type template parameters. So you can combine the two like this:
struct MyTrait { static const int value = 10; };
template <int N> struct Foo;
Foo<MyTrait::value> foo;
In this usage, the static constant is not odr-used and no definition is required. I'm speculating, but I can imagine that this kind of use was the primary intention of allowing inline initialization. For all other types, you would presumably want to have a definition anyway, so you might as well put the initializer in the definition.
This isn't an excuse, of course, and I suppose the introduction of constexpr seeks to rectify this original narrow-mindedness.

Why constexpr must be static?

An attempt to create a member of a struct with constexpr attribute without being static result in a compiler error(see below). Why is that? for a single constant value will I have this value in memory until program is terminatted instead of just scope of struct? should I back to use a macro?
struct foo
{
constexpr int n = 10;
// ...
};
error: non-static data member cannot be constexpr; did you intend to make it static?
I don't know the official rational. But surely it could lead to confusion. I, for one, can't see what it means for a non-static data member to be constexpr. Are you able to do the following?
struct foo {
constexpr int n = 10;
constexpr foo() { }
constexpr foo(int n):n(n) { } // overwrite value of n
};
Or does it mean that the initializer must be constant always, i.e you are not allowed to write the above (because n is not constant/could potentially non-constant) but allowed to say
foo f = { 10 };
The rule that constexpr int n is simply ill-formed rather than being implicitly static seems good to me, as its semantics would not be clear IMO.