using constexpr double in namespaces - c++

I'm currently getting into more C++11 stuff and jumped about constexpr. In one of my books it's said that you should use it for constants like π for example in this way:
#include <cmath>
// (...)
constexpr double PI = atan(1) * 4;
Now I wanted to put that in an own namespace, eg. MathC:
// config.h
#include <cmath>
namespace MathC {
constexpr double PI = atan(1) * 4;
// further declarations here
}
...but here IntelliSense says function call must have a constant value in a constant expression.
When I declare PI the following way, it works:
static const double PI = atan(1) * 4;
What is the actual reason the compiler doesn't seem to like constexpr but static const here? Shouldn't constexpr be eligible here, too, or is it all about the context here and constexprshouldn't be declared outside of functions?
Thank you.

What is the actual reason the compiler doesn't seem to like constexpr but static const here?
A constexpr must be evaluatable at compile time while static const does not need to be.
static const double PI = atan(1) * 4;
simply tells the compiler that PI may not be modified once it is initialized but it may be initialized at run time.

Related

Initializing constexpr with const: Different treatment for int and double [duplicate]

This question already has answers here:
Constant expression initializer for static class member of type double
(2 answers)
Closed 2 years ago.
The following code fails to compile live on Ideone:
#include <iostream>
using namespace std;
int main() {
const double kPi = 3.14;
constexpr double kPi2 = 2.0*kPi;
cout << kPi2;
}
The error message is:
prog.cpp: In function 'int main()':
prog.cpp:6:30: error: the value of 'kPi' is not usable in a constant expression
constexpr double kPi2 = 2.0*kPi;
^
prog.cpp:5:15: note: 'kPi' was not declared 'constexpr'
const double kPi = 3.14;
Substituting the const declaration for kPi with constexpr, it compiles successfully.
On the other hand, when int is used instead of double, seems like const plays well with constexpr:
#include <iostream>
using namespace std;
int main() {
const int k1 = 10;
constexpr int k2 = 2*k1;
cout << k2 << '\n';
return 0;
}
Why do int and double get different treatments for initializing a constexpr with const?
Is this a bug in the Ideone compiler? Is this required by the C++ standard? Why is that?
Was the above code UB?
P.S. I tried with Visual Studio 2015 C++ compiler, and it compiles the first code snippet (initializing constexpr with const) just fine.
Shafik Yaghmour already provided a link explaining the background.
Since I have to maintain code which has to compile with different standards, I use the following macro:
#if __cplusplus <= 199711L // lower than C++11
#define MY_CONST const
#else // C++11 and above
#define MY_CONST constexpr
#endif
The for a constexpr to be calculated at compile time everything that is used in the initialization of that constexpr also must be calculatable at compile time.
If you declare something as const it does not mean that the value will be available at compile time.
Take the following line:
const double dbl = 2.;
The double's representation is not specified by the standard so the OS will have to deal with this. So when your program is loaded by the OS there is a special assembly subroutine in your binary that will make this happen.
If you use an int the representation is specified by the standard so the compiler will know how to work with it. However the same can be achieved by making the double a constexpr as well, so the compiler will compute it in compile time. In this case the double will also be a const (you cannot make something constexpr without also making it const).
So this will work:
constexpr double kPi = 3.14;
constexpr double kPi2 = 2.0*kPi;
If you use an int the compiler will set the value of that const at compile time so the constexpr will work.
Keep in mind that different compilers can interpret const as constexpr in some cases and make it work. But that is not part of the standard.
Rule:"constexpr must be evaluate at compile time".
Let's look below code (generic example);
const double k1 = size_of_array();
k1 is constant, the value of its initializer is not known compile time but its initializer is known until run time so k1 is not constant expression. As a result a const variable is not constexpr.
But compiler see these code:
const int k1 = 10;
constexpr int k2 = 2*k1;
One exception occurs. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations [1].
You can get extra information from the links below:
Constexpr - Generalized Constant Expressions in C++11
const vs constexpr on variables | stackoverflow
Difference between constexpr and const | stackoverflow

What is the best way to define a double constant in a namespace?

What is the best way to define a double constant in a namespace? For example
// constant.h
namespace constant {
static const double PI = 3.1415926535;
}
// No need in constant.cpp
Is this the best way?
I'd say:
-- In c++14:
namespace constant
{
template <typename T = double>
constexpr T PI = T(3.1415926535897932385);
}
-- In c++11:
namespace constant
{
constexpr double PI = 3.1415926535897932385;
}
-- In c++03 :
namespace constant
{
static const double PI = 3.1415926535897932385;
}
Note that if your constant does not have a trivial type and you are within a shared library, i would advise to avoid giving it internal linkage at global/namespace scope, i don't know the theory about this but in practice it does tend to randomly mess things up :)

clang 3.5 constexpr inconsistency - errors when using double but not int

After answering using boost math constants in constexpr and suggesting OP use boost's templated function for a constexpr variable instead of the non-templated constant to quell a clang error, I decided to try to see what conditions would reproduce the error in clang. Let's try to copy what boost's macro expands to:
namespace double_constants{ static const double name = 25; }
static constexpr double SEC3 = double_constants::name;
This gives the following errors (follow along on Coliru)
clang++ -std=c++1y -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp:5:25: error: constexpr variable 'SEC3' must be initialized by a constant expression
static constexpr double SEC3 = double_constants::name;
^ ~~~~~~~~~~~~~~~~~~~~~~
main.cpp:5:32: note: read of non-constexpr variable 'name' is not allowed in a constant expression
static constexpr double SEC3 = double_constants::name;
^
main.cpp:3:49: note: declared here
namespace double_constants{ static const double name = 25; }
That's fine, we expected that. Now change double to int:
namespace double_constants{ static const int name = 25; }
static constexpr double SEC3 = double_constants::name;
No error? Needless to say I am confused. I assumed the error was because the variable is defined as const instead of constexpr, unless I'm missing something. Let's take a look at cppreference:
A constexpr variable must satisfy the following requirements:
it must be immediately constructed or assigned a value.
the constructor parameters or the value to be assigned must contain only literal values, constexpr variables and functions.
If we were to interpret this literally, then clang is justified in giving an error because name is only const, not constexpr. And apparently double is a LiteralType because:
std::cout << std::is_literal_type<double>::value;
outputs 1. So why does clang cease to complain if name is int and not a double?
P.S.: Cannot reproduce on gcc.
For clarification, the static keyword is orthogonal to the issue. So is the namespace. From what I understand, the boost macro does not wrap the static const variable in a class, but in a namespace. I've narrowed it down to these four cases:
// Does not compile
const double name = 25;
constexpr int SEC3 = name;
const double name = 25;
constexpr double SEC3 = name;
// Compiles
const int name = 25;
constexpr double SEC3 = name;
const int name = 25;
constexpr int SEC3 = name;
I can't possibly be bothered to apply static in every permutation possible to see if it makes a difference, but I doubt it does.
It's not a bug. Unfortunately the C++ standard has different static/non-static const rules for floating point types and integer types. Please see:
Why aren't static const floats allowed?
Try constexpr instead of const as in:
namespace double_constants{ constexpr double name = 25; }
and:
constexpr double name = 25;
constexpr int SEC3 = name;
Then it should work.

Illegal indirection when multiplicating

I'm starting to learn C++. Here is a problem that I have:
#include <iostream>
using namespace std;
#define PI 3.14;
int main(){
double r = 5.0;
double circle;
double inp;
circle = 2 * PI * r;
cout << circle;
cin >> inp;
}
It shows error: error C2100: illegal indirection.
I've googled but found no answer. Thanks
#define PI 3.14;
The ; is wrong, delete it.
btw, your line expands to circle = 2 * 3.14; * r;
So the compiler is then complaining about the *r, which explains the error message.
Macros are (relatively) simple substitutions so, when you write:
#define PI 3.14;
circle = 2 * PI * r;
it actually ends up as:
circle = 2 * 3.14; * r;
effectively the two statements:
circle = 2 * 3.14;
* r;
That last line would be a perfectly valid expression (albeit it not a very useful one) if r were a pointer of some description. However, given it's a double, that's where you're getting the illegal indirection from.
The use of macros is something you should generally avoid nowadays except in very specific circumstances. The use of them to provide inline functions has been subsumed mostly by the inline keyword ("mostly", because the inline keyword is only a suggestion).
In addition, using it to provide constants can be better done (with the advantage of full type support and usually better debugging) with the const keyword.
In other words, your PI constant would be better written as something like:
const double PI = 3.141592653589;
Just about the only place I use the pre-processor nowadays is for conditional compilation.
As an aside, you probably meant circumference rather than circle. The former is the length around the outside of the circle, the latter isn't really a length value at all.

const vs constexpr on variables

Is there a difference between the following definitions?
const double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;
If not, which style is preferred in C++11?
I believe there is a difference. Let's rename them so that we can talk about them more easily:
const double PI1 = 3.141592653589793;
constexpr double PI2 = 3.141592653589793;
Both PI1 and PI2 are constant, meaning you can not modify them. However only PI2 is a compile-time constant. It shall be initialized at compile time. PI1 may be initialized at compile time or run time. Furthermore, only PI2 can be used in a context that requires a compile-time constant. For example:
constexpr double PI3 = PI1; // error
but:
constexpr double PI3 = PI2; // ok
and:
static_assert(PI1 == 3.141592653589793, ""); // error
but:
static_assert(PI2 == 3.141592653589793, ""); // ok
As to which you should use? Use whichever meets your needs. Do you want to ensure that you have a compile time constant that can be used in contexts where a compile-time constant is required? Do you want to be able to initialize it with a computation done at run time? Etc.
No difference here, but it matters when you have a type that has a constructor.
struct S {
constexpr S(int);
};
const S s0(0);
constexpr S s1(1);
s0 is a constant, but it does not promise to be initialized at compile-time. s1 is marked constexpr, so it is a constant and, because S's constructor is also marked constexpr, it will be initialized at compile-time.
Mostly this matters when initialization at runtime would be time-consuming and you want to push that work off onto the compiler, where it's also time-consuming, but doesn't slow down execution time of the compiled program
constexpr indicates a value that's constant and known during compilation.
const indicates a value that's only constant; it's not compulsory to know during compilation.
int sz;
constexpr auto arraySize1 = sz; // error! sz's value unknown at compilation
std::array<int, sz> data1; // error! same problem
constexpr auto arraySize2 = 10; // fine, 10 is a compile-time constant
std::array<int, arraySize2> data2; // fine, arraySize2 is constexpr
Note that const doesn’t offer the same guarantee as constexpr, because const
objects need not be initialized with values known during compilation.
int sz;
const auto arraySize = sz; // fine, arraySize is const copy of sz
std::array<int, arraySize> data; // error! arraySize's value unknown at compilation
All constexpr objects are const, but not all const objects are constexpr.
If you want compilers to guarantee that a variable has a value that can be
used in contexts requiring compile-time constants, the tool to reach for is constexpr, not const.
A constexpr symbolic constant must be given a value that is known at compile time.
For example:
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
constexpr int c2 = n+7; // Error: we don’t know the value of c2
// ...
}
To handle cases where the value of a “variable” that is initialized with a value that is not known at compile time but never changes after initialization,
C++ offers a second form of constant (a const).
For Example:
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
const int c2 = n+7; // OK, but don’t try to change the value of c2
// ...
c2 = 7; // error: c2 is a const
}
Such “const variables” are very common for two reasons:
C++98 did not have constexpr, so people used const.
List item “Variables” that are not constant expressions (their value is not known at compile time) but do not change values after
initialization are in themselves widely useful.
Reference : "Programming: Principles and Practice Using C++" by Stroustrup
One more example to understand the difference between const and constexp.
int main()
{
int n;
cin >> n;
const int c = n; // OK: 'c' can also be initialized at run time
constexpr int e = n; // Error: 'e' must be initialized at compile time
}
Note: constexpr normally evaluated at compile-time, but they are not guaranteed to do so unless they're invoked
in a context where a constant expression is required.
constexpr int add(int a, int b)
{
return a + b;
};
int main()
{
int n = add(4, 3); // may or may not be computed at compile time
constexpr int m = add(4,3); // must be computed at compile time
}
constexpr -> Used for compile time constant. This is basically used for run time optimization.
const -> Used for run time constant.