Привет!
Мне периодически попадаются отзывы программистов, которые долгое время работали
на C++, а затем невзлюбили его и ушли на другие языки. Всегда удивляло, за что
язык можно так уж сильно невзлюбить, однако на днях я понял, за что его можно
даже люто и бешено ненавидеть. :)
Буквально до этой недели я пользовался только шаблонами классов, простых
функций, и отдельно - перегруженными функциями, практически не комбинируя это
вместе. А тут мне приспичило сделать шаблоны вычислительных функций, которые, в
зависимости от типов параметров, использовали бы различные (предельно
оптимизированные или обычные) реализации нескольких арифметических функций,
определенных, как перегруженные.
И тут мне открылось, что правила неявного преобразования в выражениях в C++ до
сих пор пребывают в каменном веке. Я-то об этом давно забыл, уже лет двадцать
используя максимальный уровень предупреждений, и наивно полагая, что неявное
приведение int к char было возможно когда-то в 90-х, а нынче-то оно невозможно
в принципе. Оказалось, что очень даже возможно, поэтому для пары параметров
(int, int) компилятор считает "подходящими" перегруженные (int, char), и даже
(char, short). Как такое можно оправдать в XXI веке и профессиональном языке, я
не понимаю, но это факт. В результате, при наличии среди перегруженных только
одной безопасно подходящей к данным параметром функции, компилятор все равно
утверждает, что у него есть и другие варианты, и поэтому я должен позаботиться
об уточнениях.
Выписывать отдельно каждую реализацию, пусть и примитивную, для всех вариантов
используемых типов ([unsigned] int, [unsigned] long, [unsigned] long64), и
трех-четырех параметров - это запредельная тупость и откровенный идиотизм.
Вдобавок нет никакой (от слова совсем) выбрать функцию только по типу
результата, хотя я в упор не могу понять, чем для этого не годятся конструкции
вида "type (func (arg))" или "type var (func (arg))", однозначно определяющие
требуемый тип.
Hо выяснилось, что язык до сих пор не предлагает именно языковых средств для
управления приоритетами и доступностью перегруженных/шаблонных функций. Все это
успешно делается через шаблонное метапрограммирование.
Hет, я пару раз пытался читать Александреску, но каждый раз приходил к выводу,
что это слишком извращенно и неестественно, и пусть этим занимаются энтузиасты
и любители функциональных языков. Hо теперь-то получается, что без этих
костылей, рожденных наркоманскими мозгами, невозможно мало-мальски серьезно
использовать перегруженные функции, а уж в сочетании с шаблонными - и подавно.
Решения через шаблоны enable_if и подобные, хоть и работают, выглядят
откровенно уродливо, и требуют весьма специфического мышления для понимания
конструкций. Hе говоря уже о том, что тупо использовать std или boost я в
ядерных проектах не могу, а чтобы выдрать нужное подмножество или написать
самому, нужно разбираться в этой извращенной кухне.
Все это очень сильно напоминает идею использования в производстве небольшого
набора универсальных деталей, вроде популярных пластин и уголков в равномерную
дырочку, вместо специализированных изделий, оптимально решающих конкретные
задачи. Hу а что, ведь можно какой-нибудь стержень не вытачивать из бруска, в
сплести из проволоки, по типу каната, и он даже будет что-то держать... :)
Всего доброго!
Евгений Музыченко
eu-...@muzy-chen-ko.net (все дефисы убрать)