3

我刚刚发现一个constexpr方法可以正确返回在执行过程中发生变化的类成员的值。我的问题是,如果constexpr方法应该在编译时完全评估,这怎么可能?

下面的示例正确输出Value: 0然后Value: 5. 更重要的是,如果我将其更改a.change(5)为编译器无法预测的内容(例如,a.change(atoi(argv[1]))a.change(rand() % 10 + 1)仍然可以工作。为什么?为什么它甚至可以编译?

#include <iostream>

class A
{
    public:
        void change(int value) { x = value; }
        int get() const { return x; }
        constexpr int value() const noexcept { return x; }
    private:
        int x{0};
};

int main()
{
    A a;

    std::cout << "Value: "  << a.get() << std::endl;
    a.change(5);
    std::cout << "Value: "  << a.get() << std::endl;
}

先感谢您

4

3 回答 3

5

在您的示例中,您甚至没有调用该constexpr函数,而是在调用get,而不是constexpr

但是,constexpr函数可以在编译时进行评估,如果编译时评估是不可能的,也可以在运行时进行评估。

如果您调用value而不是get,它仍然可以工作,并且该函数将在运行时进行评估。

为了强制编译时评估,您可以编写

constexpr auto val = a.value();

如果无法进行编译时评估,这确实会给您一个错误。

于 2021-07-28T08:01:30.113 回答
4

constexpr意味着您可以在核心常量表达式中使用该函数,只要您有constexpr参数即可。它仍然可以在其他情况下使用。

就目前而言,您不能A::value在核心常量表达式中使用,因为您无法获得constexpr A. 如果你有

class A
{
    public:
        constexpr A() = default;
        constexpr void change(int value) { x = value; }
        constexpr int get() const noexcept { return x; }
    private:
        int x{1};
};

您可以编写一个A在编译时修改的函数。

constexpr int stuff(A a) {
    a.change(10);
    return a.get();
}

在大肠杆菌上看到它

于 2021-07-28T08:09:30.697 回答
2

constexpr通常,只有在接收参数时,函数才会在编译时进行评估constexpr,对于包含this指针的方法。

#include <iostream>

class A
{
    public:
        void change(int value) { x = value; }
        constexpr int value() const noexcept { return x; }
    private:
        int x{0};
};

int main()
{
    constexpr const A foo;
    const A bar;// Const it not enough.

    static_assert(foo.value()==0);
    static_assert(bar.value()==0);// ERROR:  non-constant condition for static assertion
}
于 2021-07-28T08:11:37.617 回答