Информация об изменениях

Сообщение Re[15]: Для чего шаблонной функции нужна особая сигнатура? от 25.01.2023 5:05

Изменено 25.01.2023 5:52 so5team

Re[15]: Для чего шаблонной функции нужна особая сигнатура?
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Неужели Вы сами не видите здесь абсурдности?


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

ЕМ>Вообще ни разу. Если Вы просмотрите историю, то


Ну у меня как бы не вчера такое впечатление возникло, и даже не позавчера. Но, т.к. я ошибся, то приношу свои извинения.

ЕМ>Если компилятор не выдает ошибок, код делает то, что нужно, ничего лишнего в листингах не видно — на кой мне заморачиваться?


Потому что, к сожалению, это может быть лишь стечением обстоятельств.

ЕМ>Возможно, в Вашей практике сочетания шаблонных и нешаблонных функций с одинаковыми наборами типов встречаются регулярно.


Для получения приключений не нужно набора одинаковых типов. Вы удивитесь, но:
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++ еще и знания того, как язык может отстрелить вам ноги). Чем опытнее программист, тем большие ожидания от качества его кода и от осмысленности этого самого кода.
Re[15]: Для чего шаблонной функции нужна особая сигнатура?
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Неужели Вы сами не видите здесь абсурдности?


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

ЕМ>Вообще ни разу. Если Вы просмотрите историю, то


Ну у меня как бы не вчера такое впечатление возникло, и даже не позавчера. Но, т.к. я ошибся, то приношу свои извинения.

ЕМ>Если компилятор не выдает ошибок, код делает то, что нужно, ничего лишнего в листингах не видно — на кой мне заморачиваться?


Потому что, к сожалению, это может быть лишь стечением обстоятельств.

ЕМ>Возможно, в Вашей практике сочетания шаблонных и нешаблонных функций с одинаковыми наборами типов встречаются регулярно.


Для получения приключений не нужно набора одинаковых типов. Вы удивитесь, но:
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++ еще и знания того, как язык может отстрелить вам ноги). Чем опытнее программист, тем большие ожидания от качества его кода и от осмысленности этого самого кода.