Постоянное распространение вызова функции в C ++ - PullRequest
0 голосов
/ 01 августа 2011

Я не смог найти ответ через поиск, поэтому следующий шаг - это запрос. Скажем, у меня есть такой код:

template<class Int>
inline Int onbit(Int value, int n) {
  return value | (static_cast<Int>(1) << n);
}

Если я назову код, такой как onbit(A, 4), будет ли константа 4 распространена и оптимизирована, или я должен сделать ее шаблоном (template<int n, class Int>), чтобы она была постоянной. Является ли C ++ 0x constexpr здесь необходимым, и если да, то как именно я должен его использовать (должен int n быть const или constexpr?).

Я знаю, что constexpr будет работать с постоянными параметрами, но будет ли он частично оптимизирован, если часть параметров будет постоянной, а часть - переменной?

Резюме: Возможно ли, чтобы функция (она должна быть встроенной, верно?) Была частично оптимизирована с постоянным распространением, и, если да, каковы требования для этого?

Даже когда я пишу это, я думаю, что вызов встроенной функции будет распространять константы ...

Ответы [ 3 ]

3 голосов
/ 01 августа 2011

Вы не можете гарантировать , что все компиляторы оптимизируют этот код, хотя большинство современных компиляторов (MSVC и gcc) будут, по крайней мере, в большинстве случаев(это зависит от контекста) без учета константности, поскольку функция очень проста.

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

Так что, если оптимизация важна для вас, во всех случаях единственный ответ - проверять вашу сборку в тех случаях, когда это важно.Ваш компилятор может оптимизировать его в одном файле, но не в другом (например, когда эта функция вызывается глубоко внутри сложного шаблона, возможно, хотя и маловероятно, что оптимизатор вашего компилятора откажется и не оптимизирует его в некоторых случаях).

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

1 голос
/ 01 августа 2011

В наиболее вероятном сценарии, да, он должен делать это там, где вы вызываете Onbit (A, 4), даже в той форме, в которой вы дали код. Однако, опять же, мы можем просто надеяться, что это сделает компилятор. Вы не можете быть уверены, что оптимизация будет выполнена. Стандарты предоставили реализацию компиляторов так, как они хотят.

0 голосов
/ 01 августа 2011

Вам нужно добавить int n к аргументам шаблона, чтобы обеспечить «постоянное распространение». Имейте в виду, что вы будете генерировать новый машинный код для каждого места, где вы вызываете onbit () с другим n в качестве аргумента шаблона (я думаю, это то, с чем вам придется жить, если вы распространяете константу).

Использование функции в шаблоне не означает, что компилятор будет вставлять ее. Компилятор должен встроить сгенерированный код из шаблона (вы должны иметь возможность переопределить его, используя специфичные для компилятора расширения, если вы уверены, что думаете лучше, чем компилятор).

Однако, если вы думаете о применении комбинации постоянного распространения и встроенного расширения, я бы предложил использовать макросы. На самом деле в C / C ++ больше нет ничего, что могло бы дать вам комбинацию встраивания и постоянного распространения одним кроссплатформенным способом.

#define ON_BIT(v,n) ((v) | 1 << (n))

или что-то подобное. Я знаю, что использовать макросы - это зло ... но я все равно думаю, что ты плохой мальчик, думая о преждевременной оптимизации:).

...