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