Здравствуйте, eao197, Вы писали:
E>Здравствуйте, skeptik_, Вы писали:
E>>>Я боялся, что подобная реализация выльется в большое количество перегруженных функций (чтобы разделить случаи итераторов и указателей): _>>А зачем их делить? Шаблонная функция работает одинаково хорошо и с указателями, и с итераторами.
E>Вопрос в определении типа возвращаемого функцие значения. Для указателя тип возвращаемого значения выводится элементарно. Для итератора -- через вложенный тип reference_type.
Это делается через iterator_traits. Типа так:
template< typename ForwardIterator >
typename std::iterator_traits< ForwardIterator >::reference max_element( ForwardIterator first, ForwardIterator last )
{
ForwardIterator result = first;
if ( first != last )
while( ++first != last )
if ( *result < *first )
result = first;
return *result;
}
Re[22]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, skeptik_, Вы писали:
_>>Это делается через iterator_traits. Типа так: _>>
_>>template< typename ForwardIterator >
_>>typename std::iterator_traits< ForwardIterator >::reference max_element( ForwardIterator first, ForwardIterator last )
_>>{
_>> if ( first == last )
_>> throw std::runtime_error( "..." );
_>> ForwardIterator result = first;
_>> while( ++first != last )
_>> if ( *result < *first )
_>> result = first;
_>> return *result;
_>>}
_>>
E>Множественность реализаций max_element заменяется множественностью реализаций iterator_traits. Те же яйца -- только в профиль.
И почему это тебя волнует? Специализации iterator_traits предоставлены стандартной библиотекой. Так что хватит отмазок, скажи просто, что не знал о iterator_traits, и дело с концом.
Re[24]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, skeptik_, Вы писали:
E>>Множественность реализаций max_element заменяется множественностью реализаций iterator_traits. Те же яйца -- только в профиль.
_>И почему это тебя волнует?
есть два подхода к разработке библиотек: удобный для разработчика библиотеки и удобный для пользователя библиотеки. Первый способ, обычно, требует меньше кода в библиотеке, потому-то он и удобен для разработчика.
Существующий в STL max_element как раз служит примером первого подхода к разработке. Написали пять строчек "универсального" кода -- и дело с концом.
_> Специализации iterator_traits предоставлены стандартной библиотекой.
max_element так же предоставлен стандартной библиотекой, тем не менее он здесь обсуждается.
_>Так что хватит отмазок, скажи просто, что не знал о iterator_traits, и дело с концом.
Знал, но забыл, что равнозначно тому, что не знал. В C++ еще очень и очень много того, что я не знал никогда и не меньше того, что я основательно забыл.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[25]: Почему преждевременная оптимизация - корень всех зол
есть два подхода к разработке библиотек: удобный для разработчика библиотеки и удобный для пользователя библиотеки. Первый способ, обычно, требует меньше кода в библиотеке, потому-то он и удобен для разработчика.
Я не вижу ни малейшей разницы для пользователя между
template< typename T > T& max_element( T* first, T* last );
template< typename I > typename I::reference max_element( I first, I last );
и
template< typename I > typename std::iterator_traits<I>::reference max_element( I first, I last );
Зато вижу огромную разницу для писателя данных функций.
Re[26]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, skeptik_, Вы писали:
_>Я не вижу ни малейшей разницы для пользователя между _>
_>template< typename T > T& max_element( T* first, T* last );
_>template< typename I > typename I::reference max_element( I first, I last );
_>
_>и _>
_>template< typename I > typename std::iterator_traits<I>::reference max_element( I first, I last );
_>
_>Зато вижу огромную разницу для писателя данных функций.
Вы смотрите не туда, куда надо.
Сейчас у пользователя нет ни одной из указанных выше функций. Вот в этом-то и все дело.
Вам же нравится обсуждать то, что я с ходу не написал вариант max_element, который бы возвращал std::iterator_traits<I>::reference. Да, вы правы, я не написал. Более того, я думал, что в современном C++ это будет невозможно. Можете еще раз бросить в меня какашкой.
Только все это чисто технические вопросы, которые решаются в течении нескольких минут после начала программирования. Принципиальный вопрос в том, что было бы лучше иметь в C++ три варианта max_element (max_element с throw; max_element без nothrow, но с abort; max_element_reference без throw) или же единственный существующий max_element -- это и есть мегаудачное решение? Здесь уже знание C++ не причем.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[19]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, minorlogic, Вы писали:
M>Попробуй посмотреть на это с такой стороны.
M>Все втои варианты можно реализовать используя текущий std::max_element без накладных расходов , а вот наоборот врятли ....
M>Если вспомнить что C++ дизайнится чтобы не вносить накладных расходов по неиспользуемым фичам...
Если переименовать max_element в max_element_reference и добавить два предложенных мной варианта max_element (с throw и с abort), то у пользователя будет выбор:
— иметь максимальную производительность без проверок при поиске максимального элемента (используется max_element_reference);
— иметь безопасность ценой одного if-а (max_element с throw или abort).
Ничего не теряется по сравнению с существующим вариантом.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[21]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, minorlogic, Вы писали:
M>>Попробуй посмотреть на это с такой стороны.
M>>Все втои варианты можно реализовать используя текущий std::max_element без накладных расходов , а вот наоборот врятли ....
M>>Если вспомнить что C++ дизайнится чтобы не вносить накладных расходов по неиспользуемым фичам...
E>Если переименовать max_element в max_element_reference и добавить два предложенных мной варианта max_element (с throw и с abort), то у пользователя будет выбор: E>- иметь максимальную производительность без проверок при поиске максимального элемента (используется max_element_reference); E>- иметь безопасность ценой одного if-а (max_element с throw или abort).
E>Ничего не теряется по сравнению с существующим вариантом.
Кому это надо добавляет себе в toolbox
template< typename ForwardIterator >
typename std::iterator_traits< ForwardIterator >::reference max_element_value( ForwardIterator first, ForwardIterator last )
{
if ( first == last )
throw std::runtime_error( "empty range" );
return *std::max_element( first, last );
}
и радуется жизни. Кому не надо -- не добавляет, и тоже радуется жизни.
Re[22]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, eao197, Вы писали:
E>Я, по наивности, считал, что задача библиотек (особенно стандартных) -- избавлять программиста от написания вот такого вот кода.
Но это не значит что надо туда пхать весь функционал, который только можно придумать.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[24]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, CreatorCray, Вы писали:
E>>Я, по наивности, считал, что задача библиотек (особенно стандартных) -- избавлять программиста от написания вот такого вот кода. CC>Но это не значит что надо туда пхать весь функционал, который только можно придумать.
Хорошо, давай так: ты бы предпочел использовать:
a) только вариант max_element с необходимостью проверки возвращаемого значения;
b) вариант max_element с выбросом исключений и max_element_reference без выброса исключений
?
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[23]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, eao197, Вы писали:
E>Я, по наивности, считал, что задача библиотек (особенно стандартных) -- избавлять программиста от написания вот такого вот кода.
Не совсем так. Стандартная библиотека это компромис между компактностью, выразительностью и функциональностью . В случае std::max_element мне кажется проведена черта в нужном месте.
При желании это решение лекго дополнить или расширить своими политиками обработки ошибки.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[25]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, eao197, Вы писали:
E>Хорошо, давай так: ты бы предпочел использовать:
E>a) только вариант max_element с необходимостью проверки возвращаемого значения; E>b) вариант max_element с выбросом исключений и max_element_reference без выброса исключений
Я вклинюсь маленько , я бы предпочел оба варианта за исключением лишь синтаксиса , хотелось бы чтобы они различались в названиях.
P.S.
Проверять или нет возвращаемое значение решает програмист , есть очень много ситуаций когда заранее известно что массив не пустой.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[24]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, minorlogic, Вы писали:
E>>Я, по наивности, считал, что задача библиотек (особенно стандартных) -- избавлять программиста от написания вот такого вот кода.
M>Не совсем так. Стандартная библиотека это компромис между компактностью, выразительностью и функциональностью . В случае std::max_element мне кажется проведена черта в нужном месте.
M>При желании это решение лекго дополнить или расширить своими политиками обработки ошибки.
А чем ситуация с max_element отличается от оператора new, который по умолчанию бросает bad_alloc и имеет вариант new(nothrow)? Почему бы new не возвращать 0, а пользователям не проверять результат и не определять собственные политики обработки ошибок?
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[26]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, minorlogic, Вы писали:
M>Проверять или нет возвращаемое значение решает програмист , есть очень много ситуаций когда заранее известно что массив не пустой.
Это было бы хорошо, если бы программисты не ошибались. А они ошибаются. Программист может думать, что массив не пустой. Но это может оказаться не так в силу самых разных причин, в частности, изменения требований к программе, произведенному рефакторингу или замененному алгоритму.
Один if внутри max_element, имхо, не такая уж большая цена за повышение надежности программы _без участия_ программиста. По крайней менее в тех случаях, когда скорость max_element не критична.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[27]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, eao197, Вы писали:
E>Один if внутри max_element, имхо, не такая уж большая цена за повышение надежности программы _без участия_ программиста. По крайней менее в тех случаях, когда скорость max_element не критична.
Вы говорите только про один из вариантов использования , а стандартная библиотке статается не делать компромисов за счет снижения скорости , Попробуйте представить себе сценарий использования внутри какогонить DCT или другого цифрового алгоритма.
Аргументы ваши понятны , убедительно но недостаточны.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[25]: Почему преждевременная оптимизация - корень всех зол
есть два подхода к разработке библиотек: удобный для разработчика библиотеки и удобный для пользователя библиотеки. Первый способ, обычно, требует меньше кода в библиотеке, потому-то он и удобен для разработчика.
Если уж говорить об удобстве применения, давайте попробуем данную функцию применить. Вот например выше я имплементировал несколько сортировочных алгоритмов. В алгоритме selection sort как раз можно применить max_element:
template< typename ForwardIterator >
void selection_sort( ForwardIterator first, ForwardIterator last )
{
while( first < --last )
std::iter_swap( last, std::max_element( first, last + 1 ) );
}
Этот код неплохо демонстрирует мощь применённого (Степановым?) подхода: различные функции стандартной библиотеки очень легко комбинируются между собой за счёт унитарного подхода. На мой взгляд очень удобно.
Re[28]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, minorlogic, Вы писали:
E>>Один if внутри max_element, имхо, не такая уж большая цена за повышение надежности программы _без участия_ программиста. По крайней менее в тех случаях, когда скорость max_element не критична.
M>Вы говорите только про один из вариантов использования , а стандартная библиотке статается не делать компромисов за счет снижения скорости , Попробуйте представить себе сценарий использования внутри какогонить DCT или другого цифрового алгоритма.
Таких вариантов использования будет, максимум, несколько процентов от всех случаев использования max_element программистами. И для таких выжимателей скорости можно было бы предоставить max_element_reference с отсутствием накладных расходов.
О том и речь, что стандартную библиотеку можно было бы спроектировать с учетом удобства для большинства use case-ов, оставив низкоуровневые средства для тех, кому нужны специфические требования.
M>Аргументы ваши понятны , убедительно но недостаточны.
Да мне фиолетово. Я занимаюсь разработкой библиотек для программистов и убедился на собственном опыте, что удобство пользователя -- это одно из важнейших требований к библиотеке. Об этом и говорю -- может кому-нибудь пригодится, чтобы на своих шишках не приходилось до этой простой истины доходить.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[26]: Почему преждевременная оптимизация - корень всех зол
есть два подхода к разработке библиотек: удобный для разработчика библиотеки и удобный для пользователя библиотеки. Первый способ, обычно, требует меньше кода в библиотеке, потому-то он и удобен для разработчика.
_>Если уж говорить об удобстве применения, давайте попробуем данную функцию применить. Вот например выше я имплементировал несколько сортировочных алгоритмов. В алгоритме selection sort как раз можно применить max_element: _>
_>template< typename ForwardIterator >
_>void selection_sort( ForwardIterator first, ForwardIterator last )
_>{
_> while( first < --last )
_> std::iter_swap( last, std::max_element_reference( first, last + 1 ) );
_>}
_>
И всех делов. Не говоря уже о том, что max_element_reference гораздо точнее отражает суть происходящего, чем max_element.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.