在回答using boost math constants in constexpr并建议OP使用boost的constexpr
变量的模板化函数而不是非模板化常量来平息clang错误之后,我决定尝试查看哪些条件会重现错误在铿锵。让我们尝试复制boost的宏扩展到:
namespace double_constants{ static const double name = 25; }
static constexpr double SEC3 = double_constants::name;
这会产生以下错误(请遵循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; }
那很好,我们期待的。现在将double
更改为int
:
namespace double_constants{ static const int name = 25; }
static constexpr double SEC3 = double_constants::name;
没有错误?不用说我很困惑。我假设错误是因为变量被定义为const
而不是constexpr
,除非我遗漏了一些东西。我们来看看cppreference:
constexpr变量必须满足以下要求:
- 必须立即构建或分配值。
- 构造函数参数或要分配的值必须仅包含文字值,constexpr变量和函数。
如果我们从字面上解释这一点,那么clang就有理由给出错误,因为name
只是const
,而不是constexpr
。显然double
是LiteralType
因为:
std::cout << std::is_literal_type<double>::value;
输出1
。那么,如果name
是int
而不是double
,为什么clang会停止抱怨?
P.S。:无法在gcc上重现。
为了澄清,static
关键字与问题正交。 namespace
也是如此。根据我的理解,boost宏不会将static const
变量包装在类中,而是包含在namespace
中。我把它缩小到这四种情况:
// 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;
我不可能在每个可能的排列中应用static
,以确定它是否有所作为,但我怀疑它是否有效。
答案 0 :(得分:6)
这不是一个错误。不幸的是,C ++标准对浮点类型和整数类型有不同的静态/非静态const规则。请参阅:
Why aren't static const floats allowed?
尝试constexpr而不是const,如:
namespace double_constants{ constexpr double name = 25; }
和
constexpr double name = 25;
constexpr int SEC3 = name;
然后它应该工作。