Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса.
Вот некоторые реализации, которые я встречал
1) Просто делаем private: someFunction(); и это соответственно идет в .h, минус никому кроме класса не нужно, будет включаться везде кто использует этот класс
2) Делаем class_inl.h включаем его в cpp, все функции помечаем inline, минус, нет гарантии что они заинлайнятся, появляется новый файл в проекте
3) В cpp делаем
Здравствуйте, Igore, Вы писали:
I>Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса.
Если это просто чистая функция, которой не нужен доступ к членам класса, то прямо в сипипи-шнике, в анонимном пространстве имен. При этом "static" и "inline" являются избыточными.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Igore, Вы писали:
I>>Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса.
R>Если это просто чистая функция, которой не нужен доступ к членам класса, то прямо в сипипи-шнике, в анонимном пространстве имен. При этом "static" и "inline" являются избыточными.
Я вот пришёл к выводу, что лучше static, чем анонимное пространство имён.
Тогда в отладчике WinDbg можно легко найти функцию и поставить точку остановки.
С анонимным пространством имён получается имя вроде `anonymous namespace1`::f и отладчик не знает что с этим делать.
Здравствуйте, _NN_, Вы писали:
_NN>Я вот пришёл к выводу, что лучше static, чем анонимное пространство имён.
...
Поддерживаю. Кроме технических ограничений, когда есть более 1 ф-ции/переменной со внутренним связыванием, я предпочитаю видеть эту информацию для каждого объявления/определения, а не для блока. Вот перешёл я через go-to-definition к какой-то ф-ции — и сразу вижу, что она чисто в этом модуле используется, могу без проблем менять интрерфейс, зная, что она снаружи модуля не видна. С unnamed namespace в такой ситуации нужно глядеть выше по контексту.
Здравствуйте, _NN_, Вы писали:
_NN>Я вот пришёл к выводу, что лучше static, чем анонимное пространство имён. _NN>Тогда в отладчике WinDbg можно легко найти функцию и поставить точку остановки. _NN>С анонимным пространством имён получается имя вроде `anonymous namespace1`::f и отладчик не знает что с этим делать. _NN>К тому же есть и проблемы в VS: https://docs.microsoft.com/en-us/visualstudio/debugger/expressions-in-the-debugger?view=vs-2017#anonymous-namespaces _NN>
_NN>Anonymous namespaces are not supported. If you have the following code, you cannot add test to the watch window:
Зато анонимные пространства имен позволяют определять не только функции, но и вообще любые имена с внутренним связываением — классы, перечисления... Тут уже кому что важнее.
Здравствуйте, rg45, Вы писали:
I>>Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса. R>Если это просто чистая функция, которой не нужен доступ к членам класса, то прямо в сипипи-шнике, в анонимном пространстве имен. При этом "static" и "inline" являются избыточными.
Здравствуйте, serg_joker, Вы писали:
_>Поддерживаю. Кроме технических ограничений, когда есть более 1 ф-ции/переменной со внутренним связыванием, я предпочитаю видеть эту информацию для каждого объявления/определения, а не для блока. Вот перешёл я через go-to-definition к какой-то ф-ции — и сразу вижу, что она чисто в этом модуле используется, могу без проблем менять интрерфейс, зная, что она снаружи модуля не видна. С unnamed namespace в такой ситуации нужно глядеть выше по контексту.
Ну анонимные пространства имен ведь не обязательно делать монолитными блоками. Даже наоборот, если определять фунции попближе к месту их использования, как рекомендуют ведущие собаководы, то и код читать легче, и с определением области видимости проблем не возникает, как правило.
Здравствуйте, B0FEE664, Вы писали:
BFE>Почему inline является избыточным?
Ну от ключей компиляции зависит, если быть точным. Типовые настройки таковы, что компилятор и так будет инлайнить функции там, где посчитает это целесообразным ("any suitable" — в msvc). И в этом ему можно доверять, по моему опыту.
Здравствуйте, Igore, Вы писали:
I>Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса.
Если кратко, то 2, 3, 4, в зависимости от ситуации. 1-й случай почти всегда "не вариант", так как "чистые" функции работают с деталями реализации (могут использовать дополнительные зависимости), которые, по возможности, не должны быть видны снаружи и не должны засорять интерфейс класса. Обычно это детали реализации и не нужно их светить лишний раз.
3, 4 — второй по распространенности случай. Если нужно чтобы функция встраивалась, по возможности, то — static inline, иначе — static. Мне static удобен тем, что сначала я набиваю объявления функций в начале файла, потом идет реализация класса использующая функции, а уже потом я реализую сами функции. В случае static — VС, например, "ругается" что отсутствует реализация, что полезно. Так можно быстренько "накидать" реализацию класса, не задумываясь о деталях.
2-ой метод включает 3-й и 4-й. Но я использую его только если реализация "чистых" функций класса уж очень сложная, комплексная, файл начинает разрастаться и затрудняется навигация по коду или несколько родственных классов начинают дублировать функциональность "чистых" функций.
Здравствуйте, _NN_, Вы писали:
_NN>Я вот пришёл к выводу, что лучше static, чем анонимное пространство имён. _NN>Тогда в отладчике WinDbg можно легко найти функцию и поставить точку остановки.
А можно наконец переехать в 21 век и начать писать тесты. Юнит-тесты, функциональные тесты и прочие...
Здравствуйте, landerhigh, Вы писали:
L>Здравствуйте, _NN_, Вы писали:
_NN>>Я вот пришёл к выводу, что лучше static, чем анонимное пространство имён. _NN>>Тогда в отладчике WinDbg можно легко найти функцию и поставить точку остановки.
L>А можно наконец переехать в 21 век и начать писать тесты. Юнит-тесты, функциональные тесты и прочие...
Хотите сказать, что отладчиком не пользуетесь никогда ?
Никакие тесты не могут покрыть все случаи.
Вот, например, был на компе у клиента вирус , который портил выравнивание стека, а удалять вирус клиент не был готов.
Никакие тесты тут не помогут.
Как поняли, что происходит , добавили обход проблемы и тест для него.
Или ошибки других программ, как например антивирусов. Как это тестировать предлагаете ?
Здравствуйте, _NN_, Вы писали:
_NN>>>Я вот пришёл к выводу, что лучше static, чем анонимное пространство имён. _NN>>>Тогда в отладчике WinDbg можно легко найти функцию и поставить точку остановки.
L>>А можно наконец переехать в 21 век и начать писать тесты. Юнит-тесты, функциональные тесты и прочие...
_NN>Хотите сказать, что отладчиком не пользуетесь никогда ?
При разработке, а вышеотквоченное "помогает" только при "отладке" во время разработки (на самом деле — разработке по-ковбойски) — никогда.
Это если не начинать разговор о том, что static исключает инлайнинг, что может быть важно, когда отлавливаешь микросекунды.
_NN>Никакие тесты не могут покрыть все случаи.
И поэтому их писать вообще не надо, да? Старо как мир.
Как раз правильно написанные тесты покрывают абсолютно все возможные случаи для тестируемого юнита. Чего отладчиком не проверить никогда. При этом они прогоняются при каждой сборке и являются первой стадией верификации ака регрессивного тстирования, что вручную отладчиком... ну даже несерьезно обсуждать.
И даже когда изначально поленился покрыть все сценарии в тестах, наличие уже покрытых тестами сценариев позволяет методом исключения найти проблему намного быстрее.
_NN>Вот, например, был на компе у клиента вирус , который портил выравнивание стека, а удалять вирус клиент не был готов. _NN>Никакие тесты тут не помогут. _NN>Как поняли, что происходит , добавили обход проблемы и тест для него.
А если у него в серверной пожар, который он тушить не готов, то вы тоже напишете обход?
_NN>Или ошибки других программ, как например антивирусов. Как это тестировать предлагаете ?
Не поверишь, но во многих случаях это тоже можно выявлять и доказывать тестами.
Здравствуйте, Igore, Вы писали:
I>Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса.
I>... I>Вроде как все отлично, все должно встроится, хотя она и помечена как static. I>Плюсы, h чистый, все должно остаться в cpp
I>Хочется совета, кто что использует или что было бы хорошо использовать.
У анонимных пространств имён, впрочем, как и у статических функций, есть недостаток. На некоторых проектах для ускорения сборки используется так называемая техника unity builds, когда билд система создаёт один (или несколько, в зависимости от количества ядер) .cpp файл, в который уже включаются все остальные .cpp файлы из проекта. Так вот, при использовании такой техники возможнны конфликты имён. Мы с таким сталкивались, когда начали использовать cotire.
Здравствуйте, SaZ, Вы писали:
SaZ>У анонимных пространств имён, впрочем, как и у статических функций, есть недостаток. На некоторых проектах для ускорения сборки используется так называемая техника unity builds, когда билд система создаёт один (или несколько, в зависимости от количества ядер) .cpp файл, в который уже включаются все остальные .cpp файлы из проекта. Так вот, при использовании такой техники возможнны конфликты имён. Мы с таким сталкивались, когда начали использовать cotire.
А как в таком случае спасают static функции, ведь они тоже не обязаны быть уникальными для разных .cpp ?
Здравствуйте, Videoman, Вы писали:
V>А как в таком случае спасают static функции, ведь они тоже не обязаны быть уникальными для разных .cpp ?
Так я же и написал, что не спасают. В нашем случае поступали очень просто, в большинстве случаев делали static private функции внутри класса. Да, интерфейс загаживался, но это было не критично.
Здравствуйте, SaZ, Вы писали:
SaZ>У анонимных пространств имён, впрочем, как и у статических функций, есть недостаток. На некоторых проектах для ускорения сборки используется так называемая техника unity builds, когда билд система создаёт один (или несколько, в зависимости от количества ядер) .cpp файл, в который уже включаются все остальные .cpp файлы из проекта. Так вот, при использовании такой техники возможнны конфликты имён. Мы с таким сталкивались, когда начали использовать cotire.
V>Если кратко, то 2, 3, 4, в зависимости от ситуации. 1-й случай почти всегда "не вариант", так как "чистые" функции работают с деталями реализации (могут использовать дополнительные зависимости), которые, по возможности, не должны быть видны снаружи и не должны засорять интерфейс класса. Обычно это детали реализации и не нужно их светить лишний раз.
А почему не вариант? Может просто объявить private функцию и не порождать монстров? Стоит ли игра свеч?
Здравствуйте, rg45, Вы писали:
R>Как по мне, то нафиг-нафиг такие ускорения.
Ну мы всякое пробовали. Изначально была ситуация, когда билды игры под андройд могли занимать до 9 часов. Решали всевозможными путями. Прикручивали PCH, поняли что фигня. Делали самописные кэши для текстур, что очень помогало. Увеличивали зоопарк билд серверов. Пробовали Incredibuild, ccache (который пропатчили для нормальной работы под винду). В конечном счёте все махинации, включая юнити билды сделал сборку за приемлемое время: от 4 минут в лучшем случае до 20 минут с конвертацией всех текстур.
Здравствуйте, SaZ, Вы писали:
SaZ>Ну мы всякое пробовали. Изначально была ситуация, когда билды игры под андройд могли занимать до 9 часов. Решали всевозможными путями. Прикручивали PCH, поняли что фигня. Делали самописные кэши для текстур, что очень помогало. Увеличивали зоопарк билд серверов. Пробовали Incredibuild, ccache (который пропатчили для нормальной работы под винду). В конечном счёте все махинации, включая юнити билды сделал сборку за приемлемое время: от 4 минут в лучшем случае до 20 минут с конвертацией всех текстур.
А каков вклад юнити билдов в общее ускорение, можно как-то оценить? Вот если убрать только их, какое время сборки получится?
Здравствуйте, rg45, Вы писали:
R>А каков вклад юнити билдов в общее ускорение, можно как-то оценить? Вот если убрать только их, какое время сборки получится?
С ходу не вспомню, это года 3 назад было. Я спрошу у бывших коллег, потом отпишусь. Сборка основного движка вместе с thirdpary примерно в 10 раз, сборка Qt редактора примерно в 2-3 раза.
Надо понимать, что это в первую очередь актуально для сборки с нуля на билд серверах. Мы отказались от PCH, потому что с ним не дружил IncrediBuild.
Основной прирост достигался, насколько я помню, не для скорости компиляции а для скорости линковки.