Re[2]: Внутренние функции класса
От: rg45 СССР  
Дата: 16.01.19 13:57
Оценка: +5 :)
Здравствуйте, SaZ, Вы писали:

SaZ>У анонимных пространств имён, впрочем, как и у статических функций, есть недостаток. На некоторых проектах для ускорения сборки используется так называемая техника unity builds, когда билд система создаёт один (или несколько, в зависимости от количества ядер) .cpp файл, в который уже включаются все остальные .cpp файлы из проекта. Так вот, при использовании такой техники возможнны конфликты имён. Мы с таким сталкивались, когда начали использовать cotire.


Как по мне, то нафиг-нафиг такие ускорения.
--
Re[2]: Внутренние функции класса
От: _NN_ www.nemerleweb.com
Дата: 15.01.19 17:34
Оценка: 3 (2) +1
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, Igore, Вы писали:


I>>Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса.


R>Если это просто чистая функция, которой не нужен доступ к членам класса, то прямо в сипипи-шнике, в анонимном пространстве имен. При этом "static" и "inline" являются избыточными.


Я вот пришёл к выводу, что лучше static, чем анонимное пространство имён.

Тогда в отладчике WinDbg можно легко найти функцию и поставить точку остановки.
С анонимным пространством имён получается имя вроде `anonymous namespace1`::f и отладчик не знает что с этим делать.

К тому же есть и проблемы в VS: https://docs.microsoft.com/en-us/visualstudio/debugger/expressions-in-the-debugger?view=vs-2017#anonymous-namespaces

Anonymous namespaces are not supported. If you have the following code, you cannot add test to the watch window:

http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Внутренние функции класса
От: rg45 СССР  
Дата: 15.01.19 15:57
Оценка: +3
Здравствуйте, Igore, Вы писали:

I>Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса.


Если это просто чистая функция, которой не нужен доступ к членам класса, то прямо в сипипи-шнике, в анонимном пространстве имен. При этом "static" и "inline" являются избыточными.
--
Re[3]: Внутренние функции класса
От: Videoman Россия https://hts.tv/
Дата: 17.01.19 14:49
Оценка: +3
Здравствуйте, PavelCH, Вы писали:

PCH>А почему не вариант? Может просто объявить private функцию и не порождать монстров? Стоит ли игра свеч?

А зачем мне объявлять функцию в классе, если она полностью не зависит от класса, а нужно, только, выполнить полезное действие в реализации?
Какие преимущества:
— Не засоряется пространств имен класса. Private хоть и защищает от вызова снаружи, но участвует в перегрузке. Можно использовать короткие названия, понятные из контекста, во всех наследниках и не париться.
— Вызывая такую функцию, я полностью уверен что она не меняет инвариант класса. Т.е. на лицо меньшая связность, да еще и компилятор это проверит.
— Реализация функции может требовать дополнительный инклюды, которые не нужны в публичном интерфейсе класса, что будет засорять пространство имен и, возможно, приводить к перекомпиляции.

PCH>Стоит ли игра свеч?

О каких свечах идет речь? Если что, писанины меньше, перекомпиляций тоже.
Re: Внутренние функции класса
От: SaZ  
Дата: 16.01.19 12:58
Оценка: 3 (1) +1
Здравствуйте, Igore, Вы писали:

I>Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса.


I>...

I>Вроде как все отлично, все должно встроится, хотя она и помечена как static.
I>Плюсы, h чистый, все должно остаться в cpp

I>Хочется совета, кто что использует или что было бы хорошо использовать.


У анонимных пространств имён, впрочем, как и у статических функций, есть недостаток. На некоторых проектах для ускорения сборки используется так называемая техника unity builds, когда билд система создаёт один (или несколько, в зависимости от количества ядер) .cpp файл, в который уже включаются все остальные .cpp файлы из проекта. Так вот, при использовании такой техники возможнны конфликты имён. Мы с таким сталкивались, когда начали использовать cotire.
Re[5]: Внутренние функции класса
От: rg45 СССР  
Дата: 17.01.19 17:13
Оценка: +2
Здравствуйте, PavelCH, Вы писали:

PCH>Не совсем Вас понял. Можете привести пример? Насколько я помню там работает так:

PCH>Ну она же не доступна наружу. Возможно это не надо?
PCH>Те функции, которые требуют дополнительные инклюды, я выделяю в отдельные cpp файлы. В итоге это снижает время компиляции, если я ничего не меняю эта часть функционала не перекомпилируется.
PCH>>>Стоит ли игра свеч?
PCH>Не уверен что метод 3 занимает меньше писанины. Насчет перекомпиляция тоже вопрос. Вообще я стараюсь делать служебные функции static и невидимые в h — но они конечно не имеют доступа к

Вот в этой книжке (см. рекомендацию №44) сформулирован несложный критерий, когда следует делать функцию членом класса. Звучит этот критерий примерно так: "делайте функию членом класса в том случае, когда у вас нет другого выхода". А во всех остальных случаях, соответственно, не делайте. И можно вести бесконечно долгие дискуссии на эту тему, приводя бесчисленные доводы "за" и "против", но убедиться в истинности этого правила можно только на личном опыте.
--
Отредактировано 17.01.2019 20:03 rg45 . Предыдущая версия .
Re[8]: Внутренние функции класса
От: B0FEE664  
Дата: 21.01.19 16:53
Оценка: +2
Здравствуйте, SaZ, Вы писали:

SaZ>Есть ещё такой вариант использования лямбд для инициализации констант:

SaZ>
SaZ>const std::vector<int> v = [&]()
SaZ>{
SaZ>  std::vector<int> a;
SaZ>  // Runtime initialization code
SaZ>  while(...)
SaZ>    if(...)
SaZ>      a.push_back(...);
SaZ>  return a;
SaZ>}();

SaZ>v - тут будет константой.
SaZ>


В этом примере мне не нравится захват локальных переменных. Очень легко получить UB и не заметить:
const std::vector<int> v = [&]()
{
  std::vector<int> a;
  // Runtime initialization code
  while(v.size() != 0)
    if(true)
      a.push_back(1);
  a.push_back(2);
  return a;
}();
И каждый день — без права на ошибку...
Re: Внутренние функции класса
От: Videoman Россия https://hts.tv/
Дата: 15.01.19 21:44
Оценка: 4 (1)
Здравствуйте, Igore, Вы писали:

I>Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса.


Если кратко, то 2, 3, 4, в зависимости от ситуации. 1-й случай почти всегда "не вариант", так как "чистые" функции работают с деталями реализации (могут использовать дополнительные зависимости), которые, по возможности, не должны быть видны снаружи и не должны засорять интерфейс класса. Обычно это детали реализации и не нужно их светить лишний раз.

3, 4 — второй по распространенности случай. Если нужно чтобы функция встраивалась, по возможности, то — static inline, иначе — static. Мне static удобен тем, что сначала я набиваю объявления функций в начале файла, потом идет реализация класса использующая функции, а уже потом я реализую сами функции. В случае static — VС, например, "ругается" что отсутствует реализация, что полезно. Так можно быстренько "накидать" реализацию класса, не задумываясь о деталях.

2-ой метод включает 3-й и 4-й. Но я использую его только если реализация "чистых" функций класса уж очень сложная, комплексная, файл начинает разрастаться и затрудняется навигация по коду или несколько родственных классов начинают дублировать функциональность "чистых" функций.
Re[2]: Внутренние функции класса
От: Videoman Россия https://hts.tv/
Дата: 16.01.19 13:08
Оценка: 1 (1)
Здравствуйте, SaZ, Вы писали:

SaZ>У анонимных пространств имён, впрочем, как и у статических функций, есть недостаток. На некоторых проектах для ускорения сборки используется так называемая техника unity builds, когда билд система создаёт один (или несколько, в зависимости от количества ядер) .cpp файл, в который уже включаются все остальные .cpp файлы из проекта. Так вот, при использовании такой техники возможнны конфликты имён. Мы с таким сталкивались, когда начали использовать cotire.


А как в таком случае спасают static функции, ведь они тоже не обязаны быть уникальными для разных .cpp ?
Внутренние функции класса
От: Igore Россия  
Дата: 15.01.19 15:33
Оценка: +1
Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса.

Вот некоторые реализации, которые я встречал
1) Просто делаем private: someFunction(); и это соответственно идет в .h, минус никому кроме класса не нужно, будет включаться везде кто использует этот класс
2) Делаем class_inl.h включаем его в cpp, все функции помечаем inline, минус, нет гарантии что они заинлайнятся, появляется новый файл в проекте
3) В cpp делаем
  Скрытый текст
namespace {
namespace tmp {

void inner()
{
}

}
}

void Test::foo()
{
   tmp::inner();
// other code
}

Минусы, не знаю, встроится вызов функции или нет.
Плюсы, h чистый, все должно остаться в cpp
4) Увидел сейчас в исходника Qt-a, в cpp
  Скрытый текст
static inline inner()
{
}

void Test::foo()
{
   inner();
// other code
}

Вроде как все отлично, все должно встроится, хотя она и помечена как static.
Плюсы, h чистый, все должно остаться в cpp

Хочется совета, кто что использует или что было бы хорошо использовать.
Отредактировано 15.01.2019 15:34 Igore . Предыдущая версия .
Re[4]: Внутренние функции класса
От: rg45 СССР  
Дата: 15.01.19 21:34
Оценка: +1
Здравствуйте, serg_joker, Вы писали:

_>Поддерживаю. Кроме технических ограничений, когда есть более 1 ф-ции/переменной со внутренним связыванием, я предпочитаю видеть эту информацию для каждого объявления/определения, а не для блока. Вот перешёл я через go-to-definition к какой-то ф-ции — и сразу вижу, что она чисто в этом модуле используется, могу без проблем менять интрерфейс, зная, что она снаружи модуля не видна. С unnamed namespace в такой ситуации нужно глядеть выше по контексту.


Ну анонимные пространства имен ведь не обязательно делать монолитными блоками. Даже наоборот, если определять фунции попближе к месту их использования, как рекомендуют ведущие собаководы, то и код читать легче, и с определением области видимости проблем не возникает, как правило.
--
Re[3]: Внутренние функции класса
От: rg45 СССР  
Дата: 15.01.19 21:37
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

BFE>Почему inline является избыточным?


Ну от ключей компиляции зависит, если быть точным. Типовые настройки таковы, что компилятор и так будет инлайнить функции там, где посчитает это целесообразным ("any suitable" — в msvc). И в этом ему можно доверять, по моему опыту.
--
Отредактировано 15.01.2019 21:38 rg45 . Предыдущая версия .
Re[3]: Внутренние функции класса
От: landerhigh Пират  
Дата: 15.01.19 23:03
Оценка: +1
Здравствуйте, _NN_, Вы писали:

_NN>Я вот пришёл к выводу, что лучше static, чем анонимное пространство имён.

_NN>Тогда в отладчике WinDbg можно легко найти функцию и поставить точку остановки.

А можно наконец переехать в 21 век и начать писать тесты. Юнит-тесты, функциональные тесты и прочие...
www.blinnov.com
Re[2]: Внутренние функции класса
От: PavelCH  
Дата: 16.01.19 14:52
Оценка: +1
V>Если кратко, то 2, 3, 4, в зависимости от ситуации. 1-й случай почти всегда "не вариант", так как "чистые" функции работают с деталями реализации (могут использовать дополнительные зависимости), которые, по возможности, не должны быть видны снаружи и не должны засорять интерфейс класса. Обычно это детали реализации и не нужно их светить лишний раз.
А почему не вариант? Может просто объявить private функцию и не порождать монстров? Стоит ли игра свеч?
Нехай щастить
Re[4]: Внутренние функции класса
От: rg45 СССР  
Дата: 18.01.19 11:16
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

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


Можно-то можно, вот только нужно ли. Я понимаю, если лямбда передается параметром в какую-то другую функцию, тогда, конечно, ее использование обправдано, ибо ради этого лямбды и придуманы, собственно. А опредлить лямбду только для того, чтобы тут же ее и вызвать — польза от такого использования лично для меня сомнительна. Обычная свободная функция в анонимном пространстве имен — вот что самое оно для таких случаев — код получается и проще, и компактнее, и читабельнее. Хотя, все субъективно, конечно.
--
Re[6]: Внутренние функции класса
От: rg45 СССР  
Дата: 19.01.19 06:52
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

BFE>Чем плохо:

BFE>
BFE>void Foo::Prn()
BFE>{
BFE>    auto fnEnabled = [](bool b) -> const char* { return b ? "enabled" : "disabled"; };

BFE>    std::cout << "filter   : " << fnEnabled(m_bFilter  ) << std::endl
BFE>              << "leds     : " << fnEnabled(m_bLeds    ) << std::endl
BFE>              << "detector : " << fnEnabled(m_bDetector) << std::endl;
BFE>}
BFE>

BFE>?

Ну, хорошо, согласен, полльза от такого применения лямбд есть: это позволяет давать функциям (лямбдам) максимально простые имена, не засоряя пространство имен, пусть даже анонимное. Но, что мне все же не нравится, это то, что мы исплоьзуем лямду не потому, что нам нужна лябмда, как таковая, а просто потому, что правила языка не позволяют нам определять функции внутри других функций. Нам же никогда не прийдет в голову написать лямбду в пространстве имен там, где достаточно обычной функции. Вот поэтому такое использование лямбд кажется мне нецелевым. Хотя и оправданным в некоторых случаях, таких как этот.
--
Отредактировано 19.01.2019 6:52 rg45 . Предыдущая версия .
Re[3]: Внутренние функции класса
От: Erop Россия  
Дата: 19.01.19 07:04
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

R>>Если это просто чистая функция, которой не нужен доступ к членам класса, то прямо в сипипи-шнике, в анонимном пространстве имен. При этом "static" и "inline" являются избыточными.


BFE>Почему inline является избыточным?


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


А слова вроде static и inline влияют на связывание, видимость, ODR и тому подобные вещи, а не на то, будет подставляться то, что видно в точке вызова или нет...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Внутренние функции класса
От: IID Россия  
Дата: 19.01.19 21:27
Оценка: +1
Здравствуйте, landerhigh, Вы писали:

L>А можно наконец переехать в 21 век и начать писать тесты. Юнит-тесты, функциональные тесты и прочие...


Уже который год подряд ты всё подгораешь от отладчиков.
kalsarikännit
Re[7]: Внутренние функции класса
От: Kswapd Россия  
Дата: 20.01.19 10:36
Оценка: +1
Здравствуйте, rg45, Вы писали:

R>Ну вот не нравится, и все тут. Не для того аккумулятор покупали, чтоб капусту солить


Да вроде нормальное решение — обычная вложенная функция. Они бывают очень кстати как раз для уменьшения ненужной сложности: не засоряется scope файла. До лямбд было совсем не то: или изгаляться с макросами, или с локальными классами-функторами, которые громоздки и не имеют автоматического доступа к локальным переменным объемлющей функции; поэтому обычно и не заморачивались.

В Go, конечно, это делается элегантнее:
func something() {
    inc := func(x int) int { return x + 1 }
    i := 1
    fmt.Println(inc(i)) // prints 2
}
Re[9]: Внутренние функции класса
От: SaZ  
Дата: 21.01.19 17:22
Оценка: +1
Здравствуйте, rg45, Вы писали:

R>Так ровно того же эффекта можно добиться при помощи обычныой функции


Ну так да, просто функция будет засорять пространство имён. А лямбды можно использовать как вложенные функции (которых нет в плюсах).
Re[3]: Внутренние функции класса
От: serg_joker Украина  
Дата: 15.01.19 20:30
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Я вот пришёл к выводу, что лучше static, чем анонимное пространство имён.

...

Поддерживаю. Кроме технических ограничений, когда есть более 1 ф-ции/переменной со внутренним связыванием, я предпочитаю видеть эту информацию для каждого объявления/определения, а не для блока. Вот перешёл я через go-to-definition к какой-то ф-ции — и сразу вижу, что она чисто в этом модуле используется, могу без проблем менять интрерфейс, зная, что она снаружи модуля не видна. С unnamed namespace в такой ситуации нужно глядеть выше по контексту.
Re[3]: Внутренние функции класса
От: rg45 СССР  
Дата: 15.01.19 21:30
Оценка:
Здравствуйте, _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:


Зато анонимные пространства имен позволяют определять не только функции, но и вообще любые имена с внутренним связываением — классы, перечисления... Тут уже кому что важнее.
--
Re[2]: Внутренние функции класса
От: B0FEE664  
Дата: 15.01.19 21:34
Оценка:
Здравствуйте, rg45, Вы писали:

I>>Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса.

R>Если это просто чистая функция, которой не нужен доступ к членам класса, то прямо в сипипи-шнике, в анонимном пространстве имен. При этом "static" и "inline" являются избыточными.

Почему inline является избыточным?
И каждый день — без права на ошибку...
Re[4]: Внутренние функции класса
От: _NN_ www.nemerleweb.com
Дата: 16.01.19 05:32
Оценка:
Здравствуйте, landerhigh, Вы писали:

L>Здравствуйте, _NN_, Вы писали:


_NN>>Я вот пришёл к выводу, что лучше static, чем анонимное пространство имён.

_NN>>Тогда в отладчике WinDbg можно легко найти функцию и поставить точку остановки.

L>А можно наконец переехать в 21 век и начать писать тесты. Юнит-тесты, функциональные тесты и прочие...


Хотите сказать, что отладчиком не пользуетесь никогда ?
Никакие тесты не могут покрыть все случаи.

Вот, например, был на компе у клиента вирус , который портил выравнивание стека, а удалять вирус клиент не был готов.
Никакие тесты тут не помогут.
Как поняли, что происходит , добавили обход проблемы и тест для него.

Или ошибки других программ, как например антивирусов. Как это тестировать предлагаете ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Внутренние функции класса
От: landerhigh Пират  
Дата: 16.01.19 09:59
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>>>Я вот пришёл к выводу, что лучше static, чем анонимное пространство имён.

_NN>>>Тогда в отладчике WinDbg можно легко найти функцию и поставить точку остановки.

L>>А можно наконец переехать в 21 век и начать писать тесты. Юнит-тесты, функциональные тесты и прочие...


_NN>Хотите сказать, что отладчиком не пользуетесь никогда ?


При разработке, а вышеотквоченное "помогает" только при "отладке" во время разработки (на самом деле — разработке по-ковбойски) — никогда.
Это если не начинать разговор о том, что static исключает инлайнинг, что может быть важно, когда отлавливаешь микросекунды.

_NN>Никакие тесты не могут покрыть все случаи.


И поэтому их писать вообще не надо, да? Старо как мир.

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

_NN>Вот, например, был на компе у клиента вирус , который портил выравнивание стека, а удалять вирус клиент не был готов.

_NN>Никакие тесты тут не помогут.
_NN>Как поняли, что происходит , добавили обход проблемы и тест для него.

А если у него в серверной пожар, который он тушить не готов, то вы тоже напишете обход?

_NN>Или ошибки других программ, как например антивирусов. Как это тестировать предлагаете ?


Не поверишь, но во многих случаях это тоже можно выявлять и доказывать тестами.
www.blinnov.com
Re[3]: Внутренние функции класса
От: SaZ  
Дата: 16.01.19 13:42
Оценка:
Здравствуйте, Videoman, Вы писали:

V>А как в таком случае спасают static функции, ведь они тоже не обязаны быть уникальными для разных .cpp ?


Так я же и написал, что не спасают. В нашем случае поступали очень просто, в большинстве случаев делали static private функции внутри класса. Да, интерфейс загаживался, но это было не критично.
Отредактировано 17.01.2019 2:19 SaZ . Предыдущая версия .
Re[3]: Внутренние функции класса
От: SaZ  
Дата: 17.01.19 02:17
Оценка:
Здравствуйте, rg45, Вы писали:

R>Как по мне, то нафиг-нафиг такие ускорения.


Ну мы всякое пробовали. Изначально была ситуация, когда билды игры под андройд могли занимать до 9 часов. Решали всевозможными путями. Прикручивали PCH, поняли что фигня. Делали самописные кэши для текстур, что очень помогало. Увеличивали зоопарк билд серверов. Пробовали Incredibuild, ccache (который пропатчили для нормальной работы под винду). В конечном счёте все махинации, включая юнити билды сделал сборку за приемлемое время: от 4 минут в лучшем случае до 20 минут с конвертацией всех текстур.
Re[4]: Внутренние функции класса
От: rg45 СССР  
Дата: 17.01.19 07:41
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Ну мы всякое пробовали. Изначально была ситуация, когда билды игры под андройд могли занимать до 9 часов. Решали всевозможными путями. Прикручивали PCH, поняли что фигня. Делали самописные кэши для текстур, что очень помогало. Увеличивали зоопарк билд серверов. Пробовали Incredibuild, ccache (который пропатчили для нормальной работы под винду). В конечном счёте все махинации, включая юнити билды сделал сборку за приемлемое время: от 4 минут в лучшем случае до 20 минут с конвертацией всех текстур.


А каков вклад юнити билдов в общее ускорение, можно как-то оценить? Вот если убрать только их, какое время сборки получится?
--
Re[5]: Внутренние функции класса
От: SaZ  
Дата: 17.01.19 13:15
Оценка:
Здравствуйте, rg45, Вы писали:

R>А каков вклад юнити билдов в общее ускорение, можно как-то оценить? Вот если убрать только их, какое время сборки получится?


С ходу не вспомню, это года 3 назад было. Я спрошу у бывших коллег, потом отпишусь. Сборка основного движка вместе с thirdpary примерно в 10 раз, сборка Qt редактора примерно в 2-3 раза.
Надо понимать, что это в первую очередь актуально для сборки с нуля на билд серверах. Мы отказались от PCH, потому что с ним не дружил IncrediBuild.
Основной прирост достигался, насколько я помню, не для скорости компиляции а для скорости линковки.
Отредактировано 17.01.2019 15:44 SaZ . Предыдущая версия .
Re[4]: Внутренние функции класса
От: PavelCH  
Дата: 17.01.19 15:11
Оценка:
V>Какие преимущества:
V>- Не засоряется пространств имен класса. Private хоть и защищает от вызова снаружи, но участвует в перегрузке. Можно использовать короткие названия, понятные из контекста, во всех наследниках и не париться.
Не совсем Вас понял. Можете привести пример? Насколько я помню там работает так:
struct A {
    int get() { return 1; }
};
struct B : A {
    int get(int n) { return n; }
};

int main() {
    B b;
    return b.get(); // Тут ошибка компиляции
}

V>- Вызывая такую функцию, я полностью уверен что она не меняет инвариант класса. Т.е. на лицо меньшая связность, да еще и компилятор это проверит.
Ну она же не доступна наружу. Возможно это не надо?
V>- Реализация функции может требовать дополнительный инклюды, которые не нужны в публичном интерфейсе класса, что будет засорять пространство имен и, возможно, приводить к перекомпиляции.
Те функции, которые требуют дополнительные инклюды, я выделяю в отдельные cpp файлы. В итоге это снижает время компиляции, если я ничего не меняю эта часть функционала не перекомпилируется.
PCH>>Стоит ли игра свеч?
V>О каких свечах идет речь? Если что, писанины меньше, перекомпиляций тоже.
Не уверен что метод 3 занимает меньше писанины. Насчет перекомпиляция тоже вопрос. Вообще я стараюсь делать служебные функции static и невидимые в h — но они конечно не имеют доступа к private членам класса. Если он нужен и только в этом случае применяю private функции класса.
Нехай щастить
Re[5]: Внутренние функции класса
От: Videoman Россия https://hts.tv/
Дата: 17.01.19 16:10
Оценка:
Здравствуйте, PavelCH, Вы писали:

PCH>Не совсем Вас понял. Можете привести пример? Насколько я помню там работает так:

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

PCH>Ну она же не доступна наружу. Возможно это не надо?

Важно, не важно — общий принцип разработки гибкого и поддерживаемого кода, это маленькая связность, чем меньше тем лучше. Меньше связность — меньше контекста держать в голове и меньше вероятность нечаянно сломать.

PCH>Те функции, которые требуют дополнительные инклюды, я выделяю в отдельные cpp файлы. В итоге это снижает время компиляции, если я ничего не меняю эта часть функционала не перекомпилируется.

Т.е. если вдруг вам понадобилась одна функция, то вы создаёте для нее отдельный файл .cpp, а если, в процессе рефакторинга, она перестала быть нужна, вы всё обратно объединяете? Вы думаете это проще?

PCH>Не уверен что метод 3 занимает меньше писанины. Насчет перекомпиляция тоже вопрос. Вообще я стараюсь делать служебные функции static и невидимые в h — но они конечно не имеют доступа к private членам класса. Если он нужен и только в этом случае применяю private функции класса.

Слушайте, но бывают конечно классы, легкие снаружи, но сложные внутри, которые в реализации используют кучу функций и даже других классов. И вот в этом случае разделение на дополнительные файлы .h и.cpp оправдано, но применять такую стратегию постоянно — слишком, на мой взгляд.
Re: Внутренние функции класса
От: B0FEE664  
Дата: 18.01.19 08:52
Оценка:
Здравствуйте, Igore, Вы писали:

I>Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса.


I>1) Просто делаем private:

I>2) Делаем class_inl.h
I>3) В cpp делаем namespace {
I>4) Увидел сейчас static inline inner()

5) Лямбда.
И каждый день — без права на ошибку...
Re[2]: Внутренние функции класса
От: rg45 СССР  
Дата: 18.01.19 10:21
Оценка:
Здравствуйте, B0FEE664, Вы писали:

I>>Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса.


I>>1) Просто делаем private:

I>>2) Делаем class_inl.h
I>>3) В cpp делаем namespace {
I>>4) Увидел сейчас static inline inner()

BFE>5) Лямбда.


Даже не знаю, уместно ли вспоминать о лямбдах в данном контесте. Все-таки, лямбда — это элемент парадигмы, позволяющей оперировать функциями как данными, но никак не средство оформления. И по отношению к лямбдам возникают почти все те же вопросы, что и по отношению к функциям: какая область видимости, какое связывание, член или не член...
--
Отредактировано 18.01.2019 10:39 rg45 . Предыдущая версия . Еще …
Отредактировано 18.01.2019 10:38 rg45 . Предыдущая версия .
Отредактировано 18.01.2019 10:37 rg45 . Предыдущая версия .
Отредактировано 18.01.2019 10:35 rg45 . Предыдущая версия .
Отредактировано 18.01.2019 10:32 rg45 . Предыдущая версия .
Отредактировано 18.01.2019 10:31 rg45 . Предыдущая версия .
Отредактировано 18.01.2019 10:22 rg45 . Предыдущая версия .
Re[3]: Внутренние функции класса
От: B0FEE664  
Дата: 18.01.19 10:51
Оценка:
Здравствуйте, rg45, Вы писали:

BFE>>5) Лямбда.


R>Даже не знаю, уместно ли вспоминать о лябмдах в данном контесте. Все-таки, лябмда — это элемент парадигмы, позволяющей оперирровать функциями как данными. Но никак не средство оформления. И по отношению к лямбдам возникают почти все те же вопросы, что и по отношению к функциям: какая область видимости, какое связывание, член или не член...


Все приведённые примеры темы имеют вызов из одного метода. В этом случае функцию можно оформить прямо внутри метода в виде лямбды (не захватывая никаких переменных): никаких проблем с видимостью, связыванием и членством.
И каждый день — без права на ошибку...
Re[5]: Внутренние функции класса
От: B0FEE664  
Дата: 18.01.19 13:41
Оценка:
Здравствуйте, rg45, Вы писали:

R>Можно-то можно, вот только нужно ли. Я понимаю, если лямбда передается параметром в какую-то другую функцию, тогда, конечно, ее использование обправдано, ибо ради этого лямбды и придуманы, собственно. А опредлить лямбду только для того, чтобы тут же ее и вызвать — польза от такого использования лично для меня сомнительна. Обычная свободная функция в анонимном пространстве имен — вот что самое оно для таких случаев — код получается и проще, и компактнее, и читабельнее. Хотя, все субъективно, конечно.


Чем плохо:
void Foo::Prn()
{
    auto fnEnabled = [](bool b) -> const char* { return b ? "enabled" : "disabled"; };

    std::cout << "filter   : " << fnEnabled(m_bFilter  ) << std::endl
              << "leds     : " << fnEnabled(m_bLeds    ) << std::endl
              << "detector : " << fnEnabled(m_bDetector) << std::endl;
}

?
И каждый день — без права на ошибку...
Re[6]: Внутренние функции класса
От: rg45 СССР  
Дата: 18.01.19 13:59
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Чем плохо:

BFE>
BFE>void Foo::Prn()
BFE>{
BFE>    auto fnEnabled = [](bool b) -> const char* { return b ? "enabled" : "disabled"; };

BFE>    std::cout << "filter   : " << fnEnabled(m_bFilter  ) << std::endl
BFE>              << "leds     : " << fnEnabled(m_bLeds    ) << std::endl
BFE>              << "detector : " << fnEnabled(m_bDetector) << std::endl;
BFE>}
BFE>

BFE>?

Ну вот не нравится, и все тут. Не для того аккумулятор покупали, чтоб капусту солить А потом приходится выслушивать, мол "переусложнизмом" С++ страдает. Так понятно, если применять возможности языка не по назначению, то так оно и будет восприниматься.

Нецелевое использование

--
Отредактировано 18.01.2019 14:07 rg45 . Предыдущая версия .
Re[4]: Внутренние функции класса
От: Erop Россия  
Дата: 19.01.19 07:09
Оценка:
Здравствуйте, SaZ, Вы писали:

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



можно было просто для класса MyClass такие функции называть MyClass_f или положить их в namespace MyClass_private и не загаживать интерфейс.
Да, сделать это можно полуавтоматически, например скриптом.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Внутренние функции класса
От: rg45 СССР  
Дата: 20.01.19 09:57
Оценка:
Здравствуйте, Erop, Вы писали:

E>Потому, что при типичных настройках оптимизации компилятор с линкером сами решают что подставлять, а что нет, главное что бы определение подставляемого (или иначе используемого, кстати) было в точке вызова доступно.


А последние несколько лет компиляторы умеют даже инлайнить функции, определение которых располагается после точки использования, в той же единице трансляции. Наиболее распространенный сценарий — это обращение к приватным функциям-членам изнутри класса — инлайнинг пройдет *как надо*, независимо от последовательности определений всех функций членов в рамках единицы трансляции. Блягодаря этому, можно не заморачиваться и выбирать последовательность определений, исходя из соображений лучшего восприятия кода.
--
Отредактировано 20.01.2019 10:07 rg45 . Предыдущая версия . Еще …
Отредактировано 20.01.2019 10:04 rg45 . Предыдущая версия .
Re: Внутренние функции класса
От: prog123 Европа  
Дата: 20.01.19 20:11
Оценка:
Здравствуйте, Igore, Вы писали:

I>Добрый вечер, возник тут у меня вопрос, а как вы оформляете внутренние(служебные, чистые) функции класса.

...
I>Хочется совета, кто что использует или что было бы хорошо использовать.

pimpl еще посмотри.
Re[7]: Внутренние функции класса
От: SaZ  
Дата: 21.01.19 16:39
Оценка:
Здравствуйте, rg45, Вы писали:

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


Есть ещё такой вариант использования лямбд для инициализации констант:

const std::vector<int> v = [&]()
{
  std::vector<int> a;
  // Runtime initialization code
  while(...)
    if(...)
      a.push_back(...);
  return a;
}();

v - тут будет константой.
Re[8]: Внутренние функции класса
От: rg45 СССР  
Дата: 21.01.19 16:42
Оценка:
Здравствуйте, SaZ, Вы писали:

aZ>Есть ещё такой вариант использования лямбд для инициализации констант:


SaZ>
SaZ>const std::vector<int> v = [&]()
SaZ>{
SaZ>  std::vector<int> a;
SaZ>  // Runtime initialization code
SaZ>  while(...)
SaZ>    if(...)
SaZ>      a.push_back(...);
SaZ>  return a;
SaZ>}();

SaZ>v - тут будет константой.
SaZ>


Так ровно того же эффекта можно добиться при помощи обычныой функции
--
Re[4]: Внутренние функции класса
От: Igore Россия  
Дата: 22.01.19 08:19
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>>>5) Лямбда.


R>>Даже не знаю, уместно ли вспоминать о лябмдах в данном контесте. Все-таки, лябмда — это элемент парадигмы, позволяющей оперирровать функциями как данными. Но никак не средство оформления. И по отношению к лямбдам возникают почти все те же вопросы, что и по отношению к функциям: какая область видимости, какое связывание, член или не член...


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


Это всего лишь примеры, подразумевается многократное использование внутри cpp файла, и лямбда тут може быть только если функция маленькая и сама лямбда маленькая.
Re[5]: Внутренние функции класса
От: B0FEE664  
Дата: 22.01.19 09:21
Оценка:
Здравствуйте, Igore, Вы писали:

I>Это всего лишь примеры, подразумевается многократное использование внутри cpp файла, и лямбда тут може быть только если функция маленькая и сама лямбда маленькая.


Вчера перед сном листал стандарт, увидел пример:
auto vglambda = [](auto printer)
{
  return [=](auto&& ... ts)
         {
           printer(std::forward<decltype(ts)>(ts)...); // OK: ts is a function parameter pack
           return [=]()
                  {
                    printer(ts ...);
                  };
         };
};

auto p = vglambda( [](auto v1, auto v2, auto v3) { std::cout << v1 << v2 << v3; } );
auto q = p(1, ’a’, 3.14); // OK: outputs 1a3.14
q(); // OK: outputs 1a3.14


Смотря на такое мне совсем не кажется, что лямбда должна быть маленькой.
И каждый день — без права на ошибку...
Re[6]: Внутренние функции класса
От: rg45 СССР  
Дата: 22.01.19 09:37
Оценка:
Здравствуйте, B0FEE664, Вы писали:


BFE>Вчера перед сном листал стандарт, увидел пример:

BFE>Смотря на такое мне совсем не кажется, что лямбда должна быть маленькой.

Стандарт описывает требования к языку и поведеннию программ, но никак не к стилю кодирования. Делать выводы о хорошем стиле использования лямбд по этим примерам, это примерно то же самое, что пытаться понять, как правильно пользоваться оператором goto, по примерам из стандарта.
--
Re[7]: Внутренние функции класса
От: B0FEE664  
Дата: 22.01.19 10:10
Оценка:
Здравствуйте, rg45, Вы писали:

R>Стандарт описывает требования к языку и поведеннию программ, но никак не к стилю кодирования. Делать выводы о хорошем стиле использования лямбд по этим примерам, это примерно то же самое, что пытаться понять, как правильно пользоваться оператором goto, по примерам из стандарта.


Кстати, про goto. Лямбду можно использовать для замены goto.

Что же касается стиля и использование не по назначению — посмотрите на SFINAE.
И каждый день — без права на ошибку...
Re[8]: Внутренние функции класса
От: rg45 СССР  
Дата: 22.01.19 10:20
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Что же касается стиля и использование не по назначению — посмотрите на SFINAE.


SFINAE, как и лямбды, тоже можно использовать по-разному. Одно дело, когда SFINAE используется там, где достаточно простой специализации/перегрузки, и совсем другое, когда альтернативу трудно подобрать без значительных переделок и редизайна.
--
Отредактировано 22.01.2019 10:21 rg45 . Предыдущая версия .
Re[2]: Внутренние функции класса
От: Videoman Россия https://hts.tv/
Дата: 25.01.19 14:59
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>5) Лямбда.


Кстати, лямбды нельзя использовать в списках инициализации, а частенько бывает нужно вызвать "внутреннюю" функцию. Так что они не годятся как универсальный подход. Получается надежней [inline] static функций ничего нет .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.