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.