首页 > 解决方案 > constexpr 静态成员何时停止成为 constexpr?

问题描述

我有这个片段。

#include <iostream>
#include <string>

struct JustStr {
    JustStr(const std::string& x) : val(x) {}
    static constexpr bool pred = false;
    std::string val;
};

template <typename T>
class C {
 private:
    T x;
 public:
    C(T x_) : x(x_) {}
    void f() {
        if constexpr (!x.pred) {
                std::cout << x.val << std::endl;
            }
    }

};

template<typename T>
void f2(T x) {
    T y(x);
    if constexpr (!y.pred) {
            std::cout << x.val << std::endl;
        }
}

int main() {
    C<JustStr> c(JustStr("yes"));
    c.f();  // Fails
    f2(JustStr("yes"));  // Succeeds
    return 0;
}

我的问题是:不应该c.f();同时f2(JustStr("yes"));失败或成功吗?为什么一个失败,另一个为什么成功?

标签: c++c++17constexprif-constexpr

解决方案


有一个列表阻止表达式被视为核心常量表达式。

您不能做的一件事是评估:

this, 除非在 constexpr 函数或 constexpr 构造函数中被评估为e;

f()中,我们正在评估this以查看是什么x.pred(因为它确实是this->x.pred),但f()不是 constexpr 函数。所以这个要点排除了c.f()。如果f() constexpr,那么这将编译。

f2()中,我们不在this任何地方进行评估,因此该项目符号不适用。我们进行了左值到右值的转换,但它确实引用了一个完整的非易失性 const 对象,该对象具有前面的初始化,并使用常量表达式初始化。没有其他适用。所以没关系。


推荐阅读