Pull to refresh

Comments 36

Мне очень интересно — для кого эта статья и какое ее практическое применение?
Для программистов C++, которые хотят знать, как устроены некоторые части стандартной библиотеки.

p.s. Вообще здесь недавно был опрос, в котором большинство высказалось за более сложные «технические» статьи. На мой взгляд — это как раз такая статья, так как затрагивает довольно тонкие моменты C++
> Вообще здесь недавно был опрос
И где же?

По моим наблюдениям так тут всем наоборот сложные статьи ну вообще не по душе. (посмотрите например комментарии к этому и этому)
А воспользоваться поиском религия не позволяет?

И что вообще за идиотское замечание? Вы статьи пишите для рейтинга и кармы?
Тот факт, что народ плюсует всякий шлак (новости, истории, тренинги) — проблема именно народа. Такие статьи не несут никакой полезной нагрузки, в отличие от той, что представлена в данном топике.
Долбойобы…
нет, не для рейтинга и кармы… согласен с вами сто раз.
> А воспользоваться поиском религия не позволяет
идите на*уй, вопрос был риторический…
>>которые хотят знать
Это похвально, только Вы не озвучили целевую аудиторию и какую проблему аудитории хотите решить и чем помочь ей.

Я также как и Вы считаю, что всегда имеет смысл подстраиваться под более умных товарищей, а для этого у любого сейчас можно спрашивать ссылку на githum\bitbucket.
По моему для тех, кто хочет разобраться в STL есть исходный код.
Лично мне тяжело читать исходный код STL из-за их соглашения об именовании внутренних переменных, методов (чтобы не допустить пересечения имен с макросами, определенными пользователем). Где-то проскакивала ссылка, о том чтобы изменить ситуацию, но пока что все остается так как есть.

К тому же в полноценных реализациях много вспомогательного кода: debug assertions, обработка пограничных ситуаций и пр. Мне кажется, что нужно рассказывать именно общую идею (плюс несколько ключевых особенностей), и тогда станет проще понимать уже полноценные реализации
Если программист сам не в состоянии понять общую идею любой концепции — то и ваша статья ему мало поможет, в худшем случае он будет как обезьяна с гранатой пихать свою собственную (читай — копипаст с этой статьи) реализацию куда нужно и куда не нужно, в лучшем — захавает и завтра забудет.
Обезьян с гранатой здесь рассматривать неуместно, не дай бог, прочитают про ручное управление памятью, или возможность перегрузки глобальных операторов new/delete. Мне, например, всегда было интересно, как реализованы разные вещи в программировании. Другое дело, что не всегда хватает уровня знаний, например, я бы эту статью года 3-4 назад просто бы не понял.

Лично мне очень нравится копаться в реализации, выискивать какие-то паттерны, приемы программирования, затем обобщать эти данные. Когда разбираешь разные, казалось бы, несвязанные друг с другом вещи, а потом понимаешь, что в их основе лежит общая концепция, которой лет 50 от роду (привет LISP), вот в этот момент и ловишь настоящий кайф от проделанной работы
Тот код написан для компилятора, а не для человека.
По моему мнению, код всегда пишется для человека, что, разработчики libstdc++ не люди что-ли? Да, этот код изменяет и поддерживает гораздо меньше людей, и нужна более высокая квалификация, чтобы вносить в него изменения, но это не отменяет того факта, что когда-то его будут перечитывать, поддерживать. К сожалению, я не могу найти ссылку, где описывалось подробно, почему было выбрано такое соглашение об именовании.

Кстати, если открыть исходный код того же std::function, то можно увидеть кучу doxygen комментариев, а они то компилятору уж точно бесполезны.
В теории — конечно, для человека всё пишется. Однако, это не делает автоматически код из заголовочных файлов реализации Стандартной библиотеки для GСС (или MS компилятора) удобным или лёгким для чтения.

Пытаться «учиться» по нему, или «изучать паттерны», конечно, можно. Только зачем это другим советовать?
Я изначально спросил — для кого эта статья?

Для пользователей stl::function? Вряд-ли.
Для написания своего собственного лунного модуля? Если для этого — то если человек не может без этой статьи осознать, как реализовать — хорошего эта статья не принесет, а если способен — то она ему не нужна (он сам посмотрит в исходный код за деталями).
Для общего развития? На Хабре и в инетрнетах и так полно статей для общего развития. Представьте, если все сейчас начнут сюда сливать свои измышления по поводу тех или иных концепций.
А вы пробовали читать исходники STL? Там рассматривается куча частных случаев, которые позволяют выиграть в скорости по сравнению с более общим решением, иногда встречаются оптимизации под конкретные платформы. Например std::copy реализован с помощью десятка вспомогательных шаблонных классов.
Это не так просто читается и это не годится в качестве обучающего материала.
Да, я читал исходники STL. Но! Только когда писал свою реализацию под конкретную платформу, под конкретные задачи. До этого достаточно было понимать что те или иные контейнеры должны делать. Если лезть разбираться, какая реализация стоит за каждым интерфейсом — жизни не хватит. Не сомневаюсь, что большинство знает, как работает map, даже знает, чем AVL-дерево отличается от красно-черного. Но я очень сомневаюсь, что если я выложу пост с заголовком «Пишем свой std::map», он будет кому-то нужен.
Я вроде и не призывал курить исходный код stl, я лишь выразил свое сожаление по поводу их coding style guide. Кроме этого я добавил, что мне самому интересно ковыряться в исходниках, но это тоже на призыв никак не тянет.
Призывал antonyter, ему я и писал, что неразумно так делать
А что вас напрягает в именах? __ в начале или использование строчных букв и _ для разделения слов? Имена начинающиеся с __ зарезервированы стандартом под нужды компилятора и стандартной библиотеки. Т.е. такое именование фактически диктуется стандартом.
Небольшое уточнение: зарезервированы имена, содержашие два подчёркивания подряд где угодно (а не только в начале). C++11 [global.names] p1
UFO just landed and posted this here
Совершенно не понял, что вы пытались сказать.
UFO just landed and posted this here
Вы уж извините, но мне кажется, что, судя по тому, как вы строите предложения, ваш код, скорее всего, для сторонних разработчиков выглядит как тихий ужас. А это так, Маяковский чихнул.
Да, а я для тех, кто хочет разобраться в C++, есть стандарт. И зачем только люди пишут книги?

Что за бред?
Раз уж используются variadic templates, то лучше использовать стандартный std::unique_ptr (С++11) вместо std::auto_ptr. Ещё, наверное, можно попытаться избежать лишних копирований (move semantics).
Или shared_ptr, тогда лишних копирований не будет и не придется писать оператор присваивания и копирующий конструктор. Вот только непонятно, во всех ли случаях (например, std::bind) это будет правильно работать.
Простите, не понял как происходит работа с функторами, или ваша реализация их не поддерживает?
Полностью поддерживает, можно создать функтор с помощью std::bind, или написать лямбда функцию. Все это полностью покрывается шаблонным конструктором, в котором создается объект класса free_function_holder.

В этом и заключается вся прелесть механизма type erasure, что он позволяет спрятать любую сущность за единым интерфесом, лишь бы у него совпадала сигнатура вызываемой функции
Спасибо, с этим разобрался. Еще момент, работает ли присваивание функций/функторов?
Вы уж простите за такие вопросы, из примеров непонятно, а сходу по коду сообразить не могу.
С присваиванием накладка вышла, я забыл написать реализацию для произвольного типа, в любом случае, она будет тривиальна. Вам спасибо за то что нашли ошибку!
Кстати, я написал следующий тест
void check4()
{
	typedef function<int (void)> int_function_t;

	int_function_t f1;

	Bar bar;

	f1 = std::bind(&Bar::callMe, bar, 10);
	cout << "calling binded member function with signature int (void): " <<  f1() << endl;
}

И он успешно выполнился. Здесь произошла следующая последовательность действий:
Сначала вызвался конструктор без аргументов
Затем создался временный объект с помощью конструктора free function (в качестве параметра был передан созданный с помощью std::bind объект)
Затем вызвался оператор присваивания.

Если пометить конструктор free function как explicit, то мы увидим следующую ошибку:
error: no match for ‘operator=’ in ‘f1 = std::bind(_Func&&, _BoundArgs&& ...) [with _Func = int (Bar::*)(int); _BoundArgs = {Bar&, int}; typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type = std::_Bind<std::_Mem_fn<int (Bar::*)(int)>(Bar, int)>]((* & bar), (* &10))’


Так что, в принципе все должно работать
А чем std::function и аналоги лучше, чем простой указатель на функцию? Его тоже можно копировать, приравнивать к разным функциям и вызывать эти функции с его помощью.
Но ему нельзя присвоить функтор, а иногда надо иметь состояние.
К примеру, с помощью функтора+bind можно в одном месте создать его (и передать все нужные ему параметры), а в другом месте — вызвать.
Sign up to leave a comment.

Articles