Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Неужели Вы сами не видите здесь абсурдности?
Нет. Один термин оказался хорошим и однозначным, второй допускает несколько разных трактовок в русском языке. Дабы не путаться и избежать разночтений лучше от использования второго термина отказаться.
ЕМ>Вообще ни разу. Если Вы просмотрите историю, то
Ну у меня как бы не вчера такое впечатление возникло, и даже не позавчера. Но, т.к. я ошибся, то приношу свои извинения.
ЕМ>Если компилятор не выдает ошибок, код делает то, что нужно, ничего лишнего в листингах не видно — на кой мне заморачиваться?
Потому что, к сожалению, это может быть лишь стечением обстоятельств.
ЕМ>Возможно, в Вашей практике сочетания шаблонных и нешаблонных функций с одинаковыми наборами типов встречаются регулярно.
Для получения приключений не нужно набора одинаковых типов. Вы удивитесь, но:
void concat(char *, const char *);
template<typename T, typename U>
void concat(T, U);
уже будут выглядеть в коде идентично и будут включены компилятором в т.н. overloading set (если правильно вспомнил термин).
ЕМ>Ну, или Вам это просто в голову почему-то запало, тоже бывает.
Достаточно пару раз выкурить бамбук на тему того почему код не работает как должно.
Тут точно так же, как с пальцами в розетку. Достаточно одного раза, чтобы больше не пробовать.
ЕМ>А чтоб и то, и другое совпадало — это очень редкий, исключительный случай.
Не редкий и не исключительный. И как раз то, что человек с таким большим опытом, как у вас, этого не знает, и удивляет.
S>>как можно программировать на C++ столько лет, да еще и шаблонами в C++ пользоваться, но не помнить одной из ключевых для шаблонов вещей.
ЕМ>Если для той же комбинации типов параметров шаблон реализует в точности то же самое поведение — ничего страшного. Это значит, что так было сделано умышленно, и надобность в прежней функции пропала. А если от вызова concat ожидается новое поведение, а по факту она ведет себя по-старому, и компилятор об этом даже не предупреждает — как раз и получается плохой, негодный, кривой код.
Ох, ё, как все запущено.
Давайте я вам обратный пример приведу. Было:
| Первая версия |
| #include <iostream>
#include <vector>
namespace first_lib {
struct data_holder {};
} /* namespace first_lib */
namespace second_lib {
template<typename T> struct registry {
static std::vector<T*> items_;
};
template<typename T>
std::vector<T*> registry<T>::items_;
template<typename T>
void store(T & obj) {
registry<T>::items_.push_back(&obj);
std::cout << "second_lib::store" << std::endl;
}
} /* namespace second_lib */
int main()
{
using namespace first_lib;
using namespace second_lib;
data_holder d;
store(d);
}
|
| |
Тут подразумевается, что first_lib и second_lib -- это не ваши библиотеки. Не вы их писали, вам лишь нужно их использовать.
Результат вполне себе ожидаемый:
https://wandbox.org/permlink/sAoCSopdtpDp0xr4
Затем выходит новая версия first_lib:
| Вторая версия |
| #include <iostream>
#include <vector>
namespace first_lib {
struct data_holder {};
void store(data_holder & /*d*/) {
std::cout << "first_lib::store" << std::endl;
}
} /* namespace first_lib */
namespace second_lib {
template<typename T> struct registry {
static std::vector<T*> items_;
};
template<typename T>
std::vector<T*> registry<T>::items_;
template<typename T>
void store(T & obj) {
registry<T>::items_.push_back(&obj);
std::cout << "second_lib::store" << std::endl;
}
} /* namespace second_lib */
int main()
{
using namespace first_lib;
using namespace second_lib;
data_holder d;
store(d);
}
|
| |
И упс...
https://wandbox.org/permlink/XV9bj608aNUriPDK
Ваш код не изменился. Но работать стал иначе из-за изменений, внесенных кем-то куда-то уже после того, как вы написали и отладили свой код.
Вот в начале 1990-х что-то подобное и начало бы происходить при переходе на C++ с шаблонами и появлением обобщенного кода (если бы приоритет отдали шаблонам функций).
ЕМ>Я, ни разу не претендуя на глубокое знание языка, такого кода никогда не допускал даже интуитивно (до того, как сподобился почитать разные guidelines). Вы по-прежнему уверены, что направление критики выбрано верно?
Да. Матчасть нужно подучить. Собственно, критика направлена на это.
S>>Ну вообще-то каждый должен, да. Хотя джуниорам в C++ простительно было бы. Мидлам уже нет.
ЕМ>Возможно, дело в том, что Вы оцениваете работу программиста, как наемного работника, который обязан показать формальное знание языка, ответив на вопросы по синтаксису, семантике, тонким моментам и т.п., выполнить тестовые задания, которые оцениваются не только по результатам работы кода, но и по самому коду, уметь понимать и применять корпоративный стиль и так далее.
Программист должен написать код. Этот код должен быть осмысленным. Для чего нужны знания языка (а в случае с C++ еще и знания того, как язык может отстрелить вам ноги). Чем опытнее программист, тем большие ожидания от качества его кода и от осмысленности этого самого кода.