GCC `__attribute__ ((pure))` `предложение по & quot; входному состоянию & quot; метод получения — правильный?

Компилирование с -Wsuggest-attribute=pure заставляет GCC предлагать потенциальные функции, которые могут быть помечены __attribute__ ((pure)) в целях оптимизации.

Вот значение pure по документации GCC:

Многие функции не имеют эффектов, кроме возвращаемого значения, и их возвращаемое значение зависит только по параметрам и / или глобальным переменным. Такая функция может быть подвержена общему исключению подвыражения и оптимизации цикла так же, как и арифметический оператор. Эти функции должны быть объявлены с атрибутом pure.

Я создаю небольшой игровой движок, где у меня есть input_context класс, который содержит input_state член. input_context класс обновляет input_state Участник каждого кадра, получая глобальное состояние ввода из операционной системы.

Он также содержит несколько «получателей» для запроса состояния ввода.

Упрощенный пример:

class input_context
{
private:
input_state _input_state;

public:
void update()
{
os::fill_input_state(_input_state);
}

auto mouse_x() const noexcept
{
return _input_state._mouse_x;
}

auto mouse_y() const noexcept
{
return _input_state._mouse_y;
}

auto is_key_down(keycode k) const noexcept
{
// `_keys` is an array of `bool` values.
return _input_state._keys[k];
}
};

GCC говорит мне, что все эти «методы получения», как mouse_x(), mouse_y() а также is_key_down()являются кандидатами на __attribute__ ((pure)),

Должен ли я отметить эти методы как pure?

Я так не думаю, но предложение GCC заставляет меня задуматься об этом.

Я не уверен, как интерпретировать определение GCC pure — это говорит о том, что функции, которые полагаются только по параметрам и / или глобальным переменным должны быть помечены как таковые.

  • В некотором смысле, глобальное состояние ввода ОС может быть интерпретировано как глобальная переменная.

  • С другой стороны, «методы получения» всегда возвращают разные значения, в зависимости от _input_state переменная-член.

2

Решение

Я считаю, что все в порядке, чтобы пометить его как чистый.
Рассмотрим ваш пример в упрощенной форме с некоторыми добавленными функциями ввода-вывода:

#include <stdio.h>
class X {
int x_=0;
public:
int x() const noexcept __attribute__ ((pure)) /*__attribute__((noinline))*/;
void inc() noxcept { x_++; }
};
int X::x() const noexcept { puts("getting x"); return x_;}
int main(){
X x;
printf("%d\n", x.x() + x.x() + x.x());
x.inc();
printf("%d\n", x.x() + x.x() + x.x());
}

чистый позволяет получить:

getting x
0
getting x
3

вместо

getting x
getting x
getting x
0
getting x
getting x
getting x
3

на уровне оптимизации не менее -O1 (на более высоких уровнях вам может понадобиться добавить __attribute__((noinline)) для предотвращения встраивания).

Это нормально, если состояние изменяется между двумя последовательными вызовами к этим получателям, пока компилятор может обнаружить, что состояние изменилось.
Если вам нужно запустить non-const способ изменить состояние, тогда это не нарушение чистоты. Однако, если состояние меняется on its own (система изменяет это / другой поток изменяет это / обработчик сигнала изменяет это) таким образом, что компилятор не может знать об этом изменении, тогда pure атрибут больше не является законным.

1

Другие решения

Я думаю, что вы можете пометить эти методы как чистые, потому что они не имеют побочных эффектов.

Согласно приведенной вами документации, чистая функция может зависеть от глобальной переменной / внешнего состояния. Я думаю, это также связано с концепцией закрытия. Вы можете определить функцию f (используя Haskell, например) на основе внешней переменной:

x=1
f y = x + y

сама функция по-прежнему не имеет побочных эффектов (хотя в Haskell вы не можете изменить значение xв то время как вы можете изменить x вне функции / метода в C / C ++).

Разница между pure а также const резюмируется в этом вопросе: __attribute __ ((const)) против __attribute __ ((pure)) в GNU C

квотирование ответ там:

атрибут((const)) так же, как атрибут((чисто)), но без доступа к глобальным переменным.

1

По вопросам рекламы [email protected]