Почему метод 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;
}

заранее спасибо

3 ответа

Решение

В вашем примере вы даже не вызываете функцию, которую вы вызываете, а это не так.

Однако, constexprфункции могут быть оценены во время компиляции, но также и во время выполнения, если оценка времени компиляции невозможна.

Если вы позвонили value вместо get, он все равно будет работать, и функция будет оцениваться во время выполнения.

Чтобы принудительно оценить время компиляции, вы можете написать

      constexpr auto val = a.value();

Это действительно приведет к ошибке, если оценка времени компиляции невозможна.

означает, что вы можете использовать эту функцию в основном постоянном выражении, если у вас есть 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();
}

Смотри на колиру

функции в целом оцениваются во время компиляции, только если они получают 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
}
Другие вопросы по тегам