clang 3.5 constexpr inconsistency - 使用double但不是int时出错

时间:2014-02-10 23:36:05

标签: c++ c++11 clang constexpr

在回答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。显然doubleLiteralType因为:

std::cout << std::is_literal_type<double>::value;

输出1。那么,如果nameint而不是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,以确定它是否有所作为,但我怀疑它是否有效。

1 个答案:

答案 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;

然后它应该工作。