constexpr 与未触及的非 constexpr 参数:谁是正确的,clang 或 gcc?

constexpr with untouched non-constexpr arguments: Who is correct, clang or gcc?

我有 4 个测试用例,我相信它们都是有效的:

constexpr int f(int const& /*unused*/){
    return 1;
}

void g(int const& p){
    constexpr int a = f(p); // clang error, gcc valid

    int v = 0;
    constexpr int b = f(v); // clang valid, gcc valid

    int const& r = v;
    constexpr int c = f(r); // clang error, gcc error

    int n = p;
    constexpr int d = f(n); // clang valid, gcc valid
}

int main(){
    int p = 0;
    g(p);
}

Clang 和 GCC 仅在第一个测试用例中有所不同。

我用 clang 4 & 5 (20170319) 和 GCC 7.0.1 (20170221) 进行了测试。

如果我是对的,它将大大简化 static_assert 中 boost::hana 的使用。

[expr.const]/2:

An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:

  • [...]
  • an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either

    • it is initialized with a constant expression or

    • its lifetime began within the evaluation of e;

  • [...]

pr 都不满足条件。因此 f(p)f(r) 都不是核心常量表达式,因此它们都不能用于初始化 constexpr 变量。 Clang 是正确的。