Re[12]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.01.23 15:18
Оценка:
Здравствуйте, so5team, Вы писали:

S>донесение до вас разницы между "шаблоном функции" (ключевое слово "шаблон") и "шаблонной функцией" (ключевое слово "функция")


Честное слово, я не понимаю, зачем Вы пытаетесь донести эту разницу до меня, коли я ее отлично знаю сам. При том, что еще вчера понятия "шаблонной функции" в Вашей вселенной не было
Автор: so5team
Дата: 23.01.23
. А в моей оно было и вчера, и тридцать лет назад — так же, как и в литературе по C++.

ЕМ>>Так какие же задачи наилучшим образом решаются именно сочетанием перегрузки и шаблона, где и перегруженные, и шаблонные функции полностью совпадают по типам параметров/результата?


S>Да хотя бы банальное упрятывание реализации какой-то тяжелой и объемной реализации в .cpp-файл.


Э-э-э... Я это делаю регулярно, но применять выщеупомянутое сочетание не приходилось ни разу — именно поэтому я и удивился, увидев расхождение сигнатур. Можно пример, в котором без этого не обойтись, и который был бы из разряда "хорошей практики"?

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


S>А этого недостаточно?


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

S>всегда найдется кто-то с бородой до пола, который заявит, а я в программировании 40 лет, никогда подобной фигни не видел и не понимаю, почему так, объясните мне!


Так это нормально, что редкие в применении особенности мало кто держит в оперативной памяти. Но повторю: пока еще никто здесь не привел примера, в котором обсуждаемая особенность применялась бы иначе, как для спасения изначально неудачного кода. На каком основании ее тут возводят в ранг "каждый обязан знать!"?
Re[13]: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 24.01.23 15:52
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

S>>донесение до вас разницы между "шаблоном функции" (ключевое слово "шаблон") и "шаблонной функцией" (ключевое слово "функция")


ЕМ>Честное слово, я не понимаю, зачем Вы пытаетесь донести эту разницу до меня


Например, чтобы не читать больше про "сигнатуры шаблонных функций в C++".

ЕМ>коли я ее отлично знаю сам


Усомнюсь.

ЕМ>При том, что еще вчера понятия "шаблонной функции" в Вашей вселенной не было
Автор: so5team
Дата: 23.01.23
.


Еще несколько лет назад я сам спокойно путал "шаблон функции" и "шаблонную функцию" и использовал эти два понятия как взаимозаменяемые. Пока мне не указали на разницу. С тех пор в моей вселенной в С++ "шаблонной функции" не существует.

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


А вам зачем?

S>>А этого недостаточно?


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


Видите ли, Евгений, вы тут заняли позицию "ну попробуйте мне что-то новое о программировании рассказать, да я на C++ почти 30 лет программирую". И типа говорите о том, что используете шаблоны в C++. Но вот какая штука сильно смущает: когда человек изучает шаблоны в C++, то он должен был бы изучить и правила выбора шаблонов функций. Их там несколько и они не то, чтобы сильно замороченные, но я большинство из них забываю постоянно. За исключением самого первого: обычные функции имеют приоритет перед шаблонами.

Это вообще-то одна из базовых вещей в C++ со времен 98-го стандарта. И вот мне (вероятно не только мне) непонятно: как можно программировать на C++ столько лет, да еще и шаблонами в C++ пользоваться, но не помнить одной из ключевых для шаблонов вещей. Да еще и вести себя в стиле "ну попробуйте мне что-то..."

По поводу вашей позиции сразу хочу сделать дисклаймер: это у меня такое впечатление сложилось, если я не прав, то извините, ошибся.

ЕМ>Но повторю: пока еще никто здесь не привел примера, в котором обсуждаемая особенность применялась бы иначе, как для спасения изначально неудачного кода.


Почему же неудачного? Был код, в котором была реализация какой-то функции, скажем, concat. Реализована правильно, работала без нареканий. Появился C++98, к этому коду добавили библиотеку, в которой есть шаблон concat. Если бы приоритет отдали шаблонам функций, то при перекомпиляции вызов старой concat незаметно был бы заменен на вызов нового шаблона concat.

ЕМ>На каком основании ее тут возводят в ранг "каждый обязан знать!"?


Ну вообще-то каждый должен, да. Хотя джуниорам в C++ простительно было бы. Мидлам уже нет.
Re[14]: Для чего шаблонной функции нужна особая сигнатура?
От: vopl Россия  
Дата: 24.01.23 16:58
Оценка: 3 (1) +1
Здравствуйте, so5team, Вы писали:

S>Например, чтобы не читать больше про "сигнатуры шаблонных функций в C++".


Эмсс... Если под "шаблонной функцией" понимать инстанцию (воплощение) шаблона функции, которую стандарт называет специализацией шаблона функции — то вот определение "сигнатуры шаблонной функции в C++".

А вот тут, не то чтобы ответ на вопрос ТС, но явное подтверждение его исходной ситуации: не-шаблонная функция не является специализацией какого либо шаблона, то есть, на местном жаргоне: "не-шаблонная функция это строго не то же самое что шаблонная функция, даже если у них имя и тип совпадают". Следовательно, у них разные сигнатуры.
Re[15]: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 24.01.23 17:15
Оценка:
Здравствуйте, vopl, Вы писали:

S>>Например, чтобы не читать больше про "сигнатуры шаблонных функций в C++".


V>Эмсс... Если под "шаблонной функцией" понимать инстанцию (воплощение) шаблона функции


Э, а зачем специализацию шаблона или результат инстанциирования шаблона функции называть "шаблонной функцией"?

Ну и да, сигнатура как раз таки появляется у специализации шаблона и у результата инстанциирования шаблона. Но вот у исходного шаблона функции, как по мне, сигнатуры нет.
Re[16]: Для чего шаблонной функции нужна особая сигнатура?
От: vopl Россия  
Дата: 24.01.23 17:31
Оценка: 6 (1) +1
Здравствуйте, so5team, Вы писали:

S>Ну и да, сигнатура как раз таки появляется у специализации шаблона и у результата инстанциирования шаблона. Но вот у исходного шаблона функции, как по мне, сигнатуры нет.


сигнатура шаблона функции
Re[14]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.01.23 17:52
Оценка:
Здравствуйте, so5team, Вы писали:

S>Например, чтобы не читать больше про "сигнатуры шаблонных функций в C++".


Таки придется. Как бы Вам ни хотелось, шаблонные функции существуют, это выражение давно устоялось в литературе и документации. Соответственно, существуют и их сигнатуры.

S>Еще несколько лет назад я сам спокойно путал "шаблон функции" и "шаблонную функцию" и использовал эти два понятия как взаимозаменяемые. Пока мне не указали на разницу. С тех пор в моей вселенной в С++ "шаблонной функции" не существует.


Это высказывание просто прекрасно, оно похоже на "моя собака не кусала истца, она никогда не кусается, и вообще у меня нет никакой собаки".

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

— Вы считали два выражения равнозначными.
— Вам указали на то, что между ними есть разница.
— Вместо того, чтобы использовать каждое из них в соответствии со смыслом, Вы одно исключили полностью.

S>вы тут заняли позицию "ну попробуйте мне что-то новое о программировании рассказать, да я на C++ почти 30 лет программирую".


Вообще ни разу. Если Вы просмотрите историю, то увидите, что сведения о моем стаже программирование всплыли в тот момент, когда мне было заявлено "как можно программировать столько лет, и не знать самых азов". И получилось, что либо у меня совершенно уникальный опыт, в чем я сильно сомневаюсь, либо это таки не "самые азы", а достаточно специфическая (и потому редкая) ситуация.

S>когда человек изучает шаблоны в C++, то он должен был бы изучить и правила выбора шаблонов функций. Их там несколько и они не то, чтобы сильно замороченные, но я большинство из них забываю постоянно.


Такая же фигня. Я вообще многих формализмов не помню постоянно. Какие-то заметки делаю для себя, и периодически сверяюсь, в отдельных случаях ищу разъяснения или лезу в стандарт. Мне ж надо не экзамен сдавать, а писать работающий и эффективный код. Если компилятор не выдает ошибок, код делает то, что нужно, ничего лишнего в листингах не видно — на кой мне заморачиваться?

S>За исключением самого первого: обычные функции имеют приоритет перед шаблонами.


Возможно, в Вашей практике сочетания шаблонных и нешаблонных функций с одинаковыми наборами типов встречаются регулярно. Если мне за почти тридцать лет, после написания большого количества разнородного кода, это не встретилось ни разу — может, оно таки не является общеупотребительным? Ну, или Вам это просто в голову почему-то запало, тоже бывает.

S>Это вообще-то одна из базовых вещей в C++ со времен 98-го стандарта.


Да хоть одна из божьих заповедей, которых я с ходу тоже не перечислю. Повторяю: я исхожу из смысла, а не из формализма. А смысл в том, что подавляющее большинство функций имеет или разные имена (традиционно), или разные комбинации типов (перегрузки и шаблоны). Именно этим они и различаются, в этом и состоит смысл сигнатуры. А чтоб и то, и другое совпадало — это очень редкий, исключительный случай. Так на кой мне запоминать именно форму правила, а не его суть? Чтоб через тридцать лет она мне пригодилась впервые?

S>как можно программировать на C++ столько лет, да еще и шаблонами в C++ пользоваться, но не помнить одной из ключевых для шаблонов вещей.


Примерно так же, как много лет водить автомобиль, не помня (или даже вовсе не зная) рабочей температуры охлаждающей жидкости. Раньше, если помните, это должен был знать каждый, и указатель на панели был везде. Сейчас даже указателя в большинстве автомобилей нет.

S>Был код, в котором была реализация какой-то функции, скажем, concat. Реализована правильно, работала без нареканий. Появился C++98, к этому коду добавили библиотеку, в которой есть шаблон concat. Если бы приоритет отдали шаблонам функций, то при перекомпиляции вызов старой concat незаметно был бы заменен на вызов нового шаблона concat.


Если для той же комбинации типов параметров шаблон реализует в точности то же самое поведение — ничего страшного. Это значит, что так было сделано умышленно, и надобность в прежней функции пропала. А если от вызова concat ожидается новое поведение, а по факту она ведет себя по-старому, и компилятор об этом даже не предупреждает — как раз и получается плохой, негодный, кривой код.

А теперь смотрите, что получается: Вы, позиционируя себя знающим язык [значительно] лучше меня, не видите в таком явно опасном коде ничего плохого. Я, ни разу не претендуя на глубокое знание языка, такого кода никогда не допускал даже интуитивно (до того, как сподобился почитать разные guidelines). Вы по-прежнему уверены, что направление критики выбрано верно?

S>Ну вообще-то каждый должен, да. Хотя джуниорам в C++ простительно было бы. Мидлам уже нет.


Возможно, дело в том, что Вы оцениваете работу программиста, как наемного работника, который обязан показать формальное знание языка, ответив на вопросы по синтаксису, семантике, тонким моментам и т.п., выполнить тестовые задания, которые оцениваются не только по результатам работы кода, но и по самому коду, уметь понимать и применять корпоративный стиль и так далее. А я ни дня не работал программистом по найму, а квалификационных тестов/экзаменов вообще никогда не сдавал после вуза, а в вуз я поступал, чтоб получить диплом, ибо тогда без диплома инженерной работы не давали. Я отвечаю не за знание языка и не за вид кода, а за функциональность и работоспособность своих продуктов. Судя по тому, что мне продолжают за них платить даже при переизбытке на рынке знатоков языка, незнание отдельных тонких моментов не является обязательным для его (языка) успешного использования.
Re[17]: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 24.01.23 18:00
Оценка:
Здравствуйте, vopl, Вы писали:

S>>Ну и да, сигнатура как раз таки появляется у специализации шаблона и у результата инстанциирования шаблона. Но вот у исходного шаблона функции, как по мне, сигнатуры нет.


V>сигнатура шаблона функции


OK, спасибо, был не прав.
Re[16]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.01.23 18:01
Оценка:
Здравствуйте, so5team, Вы писали:

S>зачем специализацию шаблона или результат инстанциирования шаблона функции называть "шаблонной функцией"?


Затем, что эта функция "сделана по шаблону", "является результатом применения шаблона". Я ж выше приводил ссылки на словари — Вы их не посмотрели? "Шаблонная функция" — прямой и полностью адекватный перевод template function, о чем я уже в который раз толкую.
Re[15]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.01.23 18:05
Оценка:
Здравствуйте, vopl, Вы писали:

V>понимать инстанцию (воплощение) шаблона функции


Во, отличный термин. Я его когда-то встречал, но настолько давно, что всякие "инстанцирования" напрочь забили мозг, осталось лишь "создание экземпляра" из глубокой старины.
Re[15]: Для чего шаблонной функции нужна особая сигнатура?
От: vopl Россия  
Дата: 24.01.23 18:10
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

S>>Например, чтобы не читать больше про "сигнатуры шаблонных функций в C++".


ЕМ>Таки придется. Как бы Вам ни хотелось, шаблонные функции существуют, это выражение давно устоялось в литературе и документации. Соответственно, существуют и их сигнатуры.


Придется только если заставлять себя проявлять великую эмпатию и принимать чужие термины как свои, мимикрируя под собеседника . Вообще, я бы не сказал что "шаблонная функция" это давно устоявшееся выражение в литературе и документации, по крайней мере с тем смыслом, которым оно наделено в данном топике (инстанция шаблона функции). Обычно такое словосочетание применяют в смысле, эквивалентном "шаблону функции" но не "инстанция шаблона функции". Вот первый попавшийся пример из интернетов.
Re[16]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.01.23 21:01
Оценка:
Здравствуйте, vopl, Вы писали:

V>я бы не сказал что "шаблонная функция" это давно устоявшееся выражение в литературе и документации, по крайней мере с тем смыслом, которым оно наделено в данном топике (инстанция шаблона функции).


An instantiated function is often called a function instance (instance for short) or a template function.

The compiler creates an instance of the template by replacing the T with the specific type with which we call the template function

The terms function template and template function are sometimes used interchangeably. Strictly, however, a function template is a declaration that specifies a family of overloaded functions. [...] A template function, then, is just an instance of a function template...

The term "function template" refers to a kind of template. The term "template function" is sometimes used to mean the same thing, and sometimes to mean a function instantiated from a function template. This ambiguity is best avoided by using "function template" for the former and something like "function template instance" or "instance of a function template" for the latter.

Вообще, что в русском, что в английском, "шаблоном функции" (function template) сам экземпляр не называют никогда. А вот "шаблонной функцией" (template function) и там, и там могут называть как сам шаблон, так и вызываемое воплощение. При этом смысл, как правило, ясен из контекста.

Ну и часто встречающийся термин non-template function кагбэ намекает, что функция, "не имеющая шаблона", "не порожденная из шаблона", "не заданная шаблоном" и т.п., является "нешаблонной функцией".
Re[17]: Для чего шаблонной функции нужна особая сигнатура?
От: vopl Россия  
Дата: 25.01.23 04:34
Оценка: +2
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, vopl, Вы писали:


V>>я бы не сказал что "шаблонная функция" это давно устоявшееся выражение в литературе и документации, по крайней мере с тем смыслом, которым оно наделено в данном топике (инстанция шаблона функции).


ЕМ>An instantiated function is often called a function instance (instance for short) or a template function.


ЕМ>The compiler creates an instance of the template by replacing the T with the specific type with which we call the template function


ЕМ>The terms function template and template function are sometimes used interchangeably. Strictly, however, a function template is a declaration that specifies a family of overloaded functions. [...] A template function, then, is just an instance of a function template...


ЕМ>The term "function template" refers to a kind of template. The term "template function" is sometimes used to mean the same thing, and sometimes to mean a function instantiated from a function template. This ambiguity is best avoided by using "function template" for the former and something like "function template instance" or "instance of a function template" for the latter.


ЕМ>Вообще, что в русском, что в английском, "шаблоном функции" (function template) сам экземпляр не называют никогда. А вот "шаблонной функцией" (template function) и там, и там могут называть как сам шаблон, так и вызываемое воплощение. При этом смысл, как правило, ясен из контекста.


Согласен, есть вольности в терминологии, и в принципе можно говорить что иногда термин "template function" применяется то там то сям. Но его смысл растекается. Вот в последнем приведенном материале, ты даже сам цитату правильную вырезал: https://womble.decadent.org.uk/c++/template-faq.html

The term "function template" refers to a kind of template. The term "template function" is sometimes used to mean the same thing, and sometimes to mean a function instantiated from a function template. This ambiguity is best avoided by using "function template" for the former and something like "function template instance" or "instance of a function template" for the latter


То есть, нет никакого "давно устоявшегося выражения в литературе и документации", сплошной разброд и шатание В текущем топике лично мне таки было понятно, что ты назвал этим термином, но это не значит что все остальные должны так же с ходу раскусывать контекст именно так как ты его подразумевал, просто потому что этот термин плавающий.

ЕМ>Ну и часто встречающийся термин non-template function кагбэ намекает, что функция, "не имеющая шаблона", "не порожденная из шаблона", "не заданная шаблоном" и т.п., является "нешаблонной функцией".


Ничего он не намекает. Приведенные измышления выглядят как сугубо субъективные
Отредактировано 25.01.2023 4:36 vopl . Предыдущая версия .
Re[15]: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 25.01.23 05:05
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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


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

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


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

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


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

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


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

ЕМ>Так это нормально, что редкие в применении особенности мало кто держит в оперативной памяти. Но повторю: пока еще никто здесь не привел примера, в котором обсуждаемая особенность применялась бы иначе, как для спасения изначально неудачного кода. На каком основании ее тут возводят в ранг "каждый обязан знать!"?


Представим себе некий фреймворк, предоставляющий каркас сериализатора (перевод значений в бинарь и обратно). Его пользователем назовем программиста, который в своей прикладухе имеет всякие типы, значения которых ему нужно сериализовать. Вот в таком аспекте можно рассмотреть пример, в котором обсуждаемая особенность применяется для того чтобы "обеспечить свободу и гибкость пользователю фреймворка", а не для "спасения изначально неудачного кода"

https://github.com/vopl/dci-core-stiac/blob/master/include/dci/stiac/serialization/arch.ipp#L54

Упомянутые "свобода и гибкость" реализуются тем что прикладному программисту можно использовать как нешаблонные (в простых случаях) функции save/load, так и шаблонные, если типы сериализуемых значений носят какой нибудь комплексный характер (например как std::vector<E>) или обобщенный (например как обобщенный сериализатор для "такого то семейства перечислений")

-- добавлено позже
пример нешаблонного стиля для простых случаев
пример шаблонного для сложного значения
пример шаблонного для обобщенного
и прикладник сам может выбирать что ему использовать, просто нешаблонную перегрузку или шаблонную
Отредактировано 25.01.2023 9:04 vopl . Предыдущая версия . Еще …
Отредактировано 25.01.2023 8:45 vopl . Предыдущая версия .
Re[5]: Для чего шаблонной функции нужна особая сигнатура?
От: Pzz Россия https://github.com/alexpevzner
Дата: 25.01.23 10:21
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

Pzz>>Мои рабочие языки — это Си и Go.


ЕМ>В чем выгода от использования чистого C по сравнению с разумным подмножеством C++?


В том, что разрастание этого подмножества ограничено компилятором, а не должностной инструкцией. Первое работает всегда, второе — никогда.
Re[15]: Для чего шаблонной функции нужна особая сигнатура?
От: vopl Россия  
Дата: 25.01.23 11:08
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Таки придется. Как бы Вам ни хотелось, шаблонные функции существуют, это выражение давно устоялось в литературе и документации.


Кстати, вот выше по теме ув. σ упомянул
Автор: σ
Дата: 23.01.23
некое "templated function". Этот термин имеет очень близкое звучание с твоим "template function", гуглопереводчик их даже одинаково на русский переводит. Так вот, под templated function в стандарте определяется вовсе не "инстанция шаблона функции", это штуковина совсем про другое.

См. templated (и далее по тексту можно найти упоминание непосредственно "templated function"). Совсем упрощенно можно сказать примерно так: templated function это не-шаблонная функция внутри другой templated-штуковины или это шаблон функции.

Примеры
template <class T> void f(); // templated function, https://timsong-cpp.github.io/cppwp/temp#pre-8.1
auto l = [](auto){}; // это точно templated, наверное его можно назвать еще и function, https://timsong-cpp.github.io/cppwp/temp#pre-8.1

template <class>
struct Tpl
{
    void member(); // templated function, https://timsong-cpp.github.io/cppwp/temp#pre-8.3

    static void smember(); // templated function, https://timsong-cpp.github.io/cppwp/temp#pre-8.3

    friend bool operator!(const Tpl&) // templated function, https://timsong-cpp.github.io/cppwp/temp#pre-8.2, https://timsong-cpp.github.io/cppwp/temp#pre-note-6
    {
        auto f = [](){}; // это точно templated, наверное его можно назвать еще и function, https://timsong-cpp.github.io/cppwp/temp#pre-8.5
        return true;
    }
};

template <> void Tpl<int>::member();// специализация такая
template <> void Tpl<char>::member();// специализация сякая

int main()
{
    Tpl<int> v;

    v.member();
    /* а вот тут уже никаких templateXXX, 
       тут произошло инстанцирование шаблона функции, 
       для которого либо была выбрана какая то из имеющихся специализаций, 
       либо сформирована новая из шаблона
       и из всего этого получено нечто, что рекомендуют называть
       "function template instance" or "instance of a function template"

       но ты называешь это нечто "template function":)
    */

    return 0;
}
Re[18]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 25.01.23 11:32
Оценка:
Здравствуйте, vopl, Вы писали:

V>можно говорить что иногда термин "template function" применяется то там то сям.


Не "иногда", а регулярно.

V>Но его смысл растекается.


Сколько вообще есть терминов, имеющих единственный смысл, никак не зависящий от контекста? Механики, говоря о "моменте", свободно опускают, чего именно — силы, импульса или инерции, если это ясно из контекста. Электротехники, говоря о "массе" в смысле соединения или потенциала, не уточняют, что речь идет об общем проводе. В программировании "поток" может обозначать и поток данных, и поток команд, и единицу диспетчеризации, но смысл чаще всего таки ясен из контекста.

V>нет никакого "давно устоявшегося выражения в литературе и документации", сплошной разброд и шатание


"Устоявшимся" называют не "истинное" или "одобренное свыше", а вошедшее в общую практику. Если такое слово/выражение является объективно неверным, противоречивым, регулярно провоцирует путаницу и т.п., его имеет смысл искоренять, иначе же — зачем?

V>лично мне таки было понятно, что ты назвал этим термином, но это не значит что все остальные должны так же с ходу раскусывать контекст именно так как ты его подразумевал, просто потому что этот термин плавающий.


На мой взгляд, те, кто больше всего возмущается "нечеткостью формулировки" или "отсутствием примера кода", чаще всего мыслят в терминах конечных конструкций, а не понятий, которые они обозначают. Так же, как среди математиков есть те, кто опишет множество четных чисел, как "множество четных чисел", а есть те, кто опишет его, как "подмножесво Z, такое, что для любого элемента n справедливо n mod 2 = 0". Второе хорошо для сугубо теоретических исследований, а для практики больше подходит первое.
Re[6]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 25.01.23 11:36
Оценка:
Здравствуйте, Pzz, Вы писали:

ЕМ>>В чем выгода от использования чистого C по сравнению с разумным подмножеством C++?


Pzz>В том, что разрастание этого подмножества ограничено компилятором, а не должностной инструкцией.


Ну да, при отсутствии свободы в выборе подмножества, такое естественное ограничение вполне разумно.
Re[6]: Для чего шаблонной функции нужна особая сигнатура?
От: σ  
Дата: 25.01.23 12:46
Оценка:
Pzz>>>Мои рабочие языки — это Си и Go.

ЕМ>>В чем выгода от использования чистого C по сравнению с разумным подмножеством C++?


Pzz>В том, что разрастание этого подмножества ограничено компилятором, а не должностной инструкцией. Первое работает всегда, второе — никогда.


Для Си тоже могут быть нужны должностные инструкции. А то есть компиляторы с __attribute__((cleanup(...))) и прочими приятными дополнениями.
Re: Для чего шаблонной функции нужна особая сигнатура?
От: B0FEE664  
Дата: 25.01.23 17:47
Оценка: 21 (2) +2
Здравствуйте, Евгений Музыченко, Вы писали:

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


Рассмотрим полную специализацию (худых специализаций не бывает) шаблонной функции:
template<> void f<>(char* p);

Такая декларация нам говорит, что где-то объявлена шаблонная функция, но как именно она выглядит мы не знаем, так как декларации функции возможны разные. Более того, возможны даже некоторые их комбинации за счёт перегрузок.
Теперь рассмотрим вызов этой функции:
char* p = nullptr;
f(p);

Зададимся вопросом: существует ли такой код, для которого этот вызов не будет вызовом функции template<> void f<>(char* p);?
Я, таки, напишу это: не всё так однозначно!
Но всё логично.
Дело в том, что прежде всего из всего набора функций f, нам нужно выбрать ту, что наиболее близко подходит по параметру к указанному вызову.
допустим, изначально у нас есть две перегрузки функции f:
такая:
template<class T> void f(T x); // 1

и такая:
template<class T> void f(T* pX); // 2

а исходной специализации ещё нет:
template<> void f<>(char* p);
Надеюсь вы согласитесь, что вызов:
char* p = nullptr;
f(p);

должен вызвать функцию номер 2: template<class T> void f(T* pX);
Т.е. следующий код напечатает p:
#include <iostream>
template<class T> void f(T pX)  {std::cout << "t\n";}
template<class T> void f(T* pX)  {std::cout << "p\n";}
int main()
{
  char* p = nullptr;
  f(p);
  return 0;      
}


А теперь добавим вызов f до второй перегрузки:
#include <iostream>
template<class T> void f(T pX)  {std::cout << "t\n";}

void g()
{
  char* p =nullptr;
  f(p);
}

template<class T> void f(T* pX)  {std::cout << "p\n";}
int main()
{
  char* p =nullptr;
  f(p);
  g();
  return 0;      
}


В функции g() при вызове f(p); ничего о template<class T> void f(T* pX) не известно, поэтому в выводе мы увидим
t
p


Если вы думаете, что тут что-то не так, то проверим тот же код с обычными функциями:
#include <iostream>
void old(short n)  {std::cout << "short\n";}
template<class T> void f(T pX)  {std::cout << "t\n";}

void g()
{
  char* p =nullptr;
  f(p);
  old(0);
}

template<class T> void f(T* pX)  {std::cout << "p\n";}
void old(int f)  {std::cout << "int\n";}
int main()
{
  g();
  char* p =nullptr;
  f(p);
  old(0);
  return 0;      
}

Из g() будет вызвана функция void old(short n), а из main() — void old(int f), хотя вызовы совершенно одинаковы old(0);!
Вывод:
t
short
p
int


Таким образом поведение шаблонных функций соответствует поведению обычных функций.

А теперь добавим специализацию шаблонной функции:
#include <iostream>
void old(short n)  {std::cout << "short\n";}
template<class T> void f(T pX)  {std::cout << "t\n";}
template<> void f<>(char* p) {std::cout << "char* spec 1\n";}

void g()
{
  char* p =nullptr;
  f(p);
  old(0);
}

template<class T> void f(T* pX)  {std::cout << "p\n";}
void old(int f)  {std::cout << "int\n";}
int main()
{
  g();
  char* p =nullptr;
  f(p);
  old(0);
  return 0;      
}

Вывод:
char* spec 1
short
p
int


Как вы видите, вызов f(p); из main(), не вызывает template<> void f<>(char* p), а вызывает template<class T> void f(T* pX). Вызывается шаблонный вариант так как, при выборе из двух функций template<class T> void f(T pX) и template<class T> void f(T* pX), вторая подходит лучше, а для нее специализации нет, так как специализация сделана только для первой функции. Как видите, при линковке перегрузка шаблонной функции может скрывать специализацию шаблонной функции, а вот скрыть перегрузку обычной функции шаблонная функция не может:

#include <iostream>
void old(short n)  {std::cout << "short\n";}
template<class T> void f(T pX)  {std::cout << "t\n";}
template<> void f(char* p) {std::cout << "char* spec 1\n";}
void f(char* p) {std::cout << "simple char*\n";}

void g()
{
  char* p =nullptr;
  f(p);
  old(0);
}

template<class T> void f(T* pX)  {std::cout << "p\n";}
template<> void f<>(char* p) {std::cout << "char* spec 2\n";}
void old(int f)  {std::cout << "int\n";}
int main()
{
  g();
  char* p =nullptr;
  f(p);
  old(0);
  return 0;      
}

simple char*
short
simple char*
int

А раз функции линкуются по разному, значит они должны иметь разные сигнатуры.
И каждый день — без права на ошибку...
Отредактировано 25.01.2023 17:51 B0FEE664 . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.