Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 21.01.23 13:32
Оценка: :)
Хотел в одной из библиотек сделать финт ушами: в заголовке оставить объявления нескольких одноименных функций с перегрузкой типов параметров, а в модуле реализовать их общим шаблоном, явно определив версии с допустимыми комбинациями параметров. По замыслу, это позволило бы линковать с ней другие библиотеки без перекомпиляции их исходников. Но оказалось, что [как минимум] VC++ дает шаблонным функциям сигнатуры, отличные от сигнатур обычных функций, и линковки таки не получается.

Какой в этом может быть смысл? Чем функция с определенными типами параметров и результата, реализованная через шаблон, в плане линковки отличается от функции с теми же типами, но без шаблона?
Re: Для чего шаблонной функции нужна особая сигнатура?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 21.01.23 13:37
Оценка: 1 (1) +3
Здравствуйте, Евгений Музыченко, Вы писали:

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


Ну, нешаблонная функция имеет приоритет перед шаблонной, может, для этого?


ЗЫ А вообще, ты — смешной. Костеришь использование побочных эффектов шаблонов, хотя это давно стало стандартом, и всё давно разжевано уже донельзя, а сам какие-то хаки пытаешься изобрести
Маньяк Робокряк колесит по городу
Отредактировано 21.01.2023 13:40 Marty . Предыдущая версия .
Re[2]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 21.01.23 13:48
Оценка:
Здравствуйте, Marty, Вы писали:

M>Костеришь использование побочных эффектов шаблонов, хотя это давно стало стандартом, и всё давно разжевано уже донельзя


Ну вот в тех же исламских странах ношение хиджаба и прочих причиндалов стало стандартом на несколько тысяч лет раньше, и тоже "давно разжевано уже донельзя" — значит, следует перестать это костерить и начать приветствовать?

А в Китае лишь сравнительно недавно перестали бинтовать ступни маленьким девочкам. Если бы этот обычай никто не костерил — думаешь, все равно перестали бы?
Re[3]: Для чего шаблонной функции нужна особая сигнатура?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 21.01.23 13:58
Оценка: -2 :)
Здравствуйте, Евгений Музыченко, Вы писали:

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


ЕМ>А в Китае лишь сравнительно недавно перестали бинтовать ступни маленьким девочкам. Если бы этот обычай никто не костерил — думаешь, все равно перестали бы?


Ну, а ты придумал какой-то расширитель анального отверстия, и жалуешься, что тебе почему-то больно. А так смотри, может ещё кому-нибудь бы понравилось, и все стали бы себе жопку расширять, и вошло бы в традиции на тысячелетия. Но тебя это не парит, тебя хиджабы волнуют. А что, зато запоры не мучают
Маньяк Робокряк колесит по городу
Re: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 23.01.23 05:24
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Хотел в одной из библиотек сделать финт ушами: в заголовке оставить объявления нескольких одноименных функций с перегрузкой типов параметров, а в модуле реализовать их общим шаблоном, явно определив версии с допустимыми комбинациями параметров. По замыслу, это позволило бы линковать с ней другие библиотеки без перекомпиляции их исходников. Но оказалось, что [как минимум] VC++ дает шаблонным функциям сигнатуры, отличные от сигнатур обычных функций, и линковки таки не получается.


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

// dummy.hpp-файл.
#pragma once

void dummy(char, unsigned int);
void dummy(unsigned int, float);
void dummy(float, unsigned long);

// dummy.cpp файл.
#include "dummy.hpp"

template<typename A, typename B>
void dummy_impl(A a, B b) {...}

void dummy(char a, unsigned int b) { dummy_impl(a, b); }
void dummy(unsigned int a, float b) { dummy_impl(a, b); }
void dummy(float a, unsigned long b) { dummy_impl(a, b); }


?
Отредактировано 23.01.2023 5:57 so5team . Предыдущая версия .
Re[2]: Для чего шаблонной функции нужна особая сигнатура?
От: K13 http://akvis.com
Дата: 23.01.23 07:41
Оценка: +1
Здравствуйте, so5team, Вы писали:

S>Здравствуйте, Евгений Музыченко, Вы писали:


ЕМ>>Хотел в одной из библиотек сделать финт ушами: в заголовке оставить объявления нескольких одноименных функций с перегрузкой типов параметров, а в модуле реализовать их общим шаблоном, явно определив версии с допустимыми комбинациями параметров. По замыслу, это позволило бы линковать с ней другие библиотеки без перекомпиляции их исходников. Но оказалось, что [как минимум] VC++ дает шаблонным функциям сигнатуры, отличные от сигнатур обычных функций, и линковки таки не получается.


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


S>
S>// dummy.hpp-файл.
S>#pragma once

S>void dummy(char, unsigned int);
S>void dummy(unsigned int, float);
S>void dummy(float, unsigned long);

S>// dummy.cpp файл.
S>#include "dummy.hpp"

S>template<typename A, typename B>
S>void dummy_impl(A a, B b) {...}

S>void dummy(char a, unsigned int b) { dummy_impl(a, b); }
S>void dummy(unsigned int a, float b) { dummy_impl(a, b); }
S>void dummy(float a, unsigned long b) { dummy_impl(a, b); }
S>


S>?


как я понял, он хочет просто написать шаблон dummy(), явно инстанцировать нужные комбинации и всё.
без прокидывания вызова.
Re[3]: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 23.01.23 07:44
Оценка:
Здравствуйте, K13, Вы писали:

K13>как я понял, он хочет просто написать шаблон dummy(), явно инстанцировать нужные комбинации и всё.

K13>без прокидывания вызова.

У меня была и такая версия, но в формулировке Евгения не было термина "инстанциирование", который здесь явно напрашивался и не позволил бы трактовать условие задачи иначе. Поэтому и решил уточнить с примером кода, для устранения разночтений.
Re[2]: Для чего шаблонной функции нужна особая сигнатура?
От: Videoman Россия https://hts.tv/
Дата: 23.01.23 08:28
Оценка:
Здравствуйте, so5team, Вы писали:

S>Здравствуйте, Евгений Музыченко, Вы писали:


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


Как я понял, он спрашивает почему, когда он делает полную специализацию шаблонной функции, её манглинг не превращается в полностью такой же как у простой функции с такими же параметрами и её нельзя вызвать из Cи.
Ответ очевиден: потому-что это другая функция и для вызова из Си нужны обертки.
Re[2]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 09:28
Оценка:
Здравствуйте, so5team, Вы писали:

S>без примеров кода однозначно понять что же вам нужно бывает затруднительно


В данном случае то, что мне нужно — отдельный вопрос. Основной вопрос был о том, для чего сигнатура шаблонной функции отличается от сигнатуры перегруженной функции с той же комбинацией типов. Один из вариантов — для обеспечения приоритета. Еще могут быть какие-то основания?
Re[4]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 09:37
Оценка:
Здравствуйте, so5team, Вы писали:

S>в формулировке Евгения не было термина "инстанциирование"


Там было конкретное описание действия: "явно определив версии с допустимыми комбинациями параметров". "Инстанцирование" — это не термин, а уродливая калька для тех, кто мыслит не понятиями, а идентификаторами. Если же мыслить понятиями, то как еще можно понять выражение "явно определив версии", кроме как "instantiating"? Что еще можно сделать с шаблоном функции, чтобы "явно определить" его версии?
Отредактировано 23.01.2023 9:38 Евгений Музыченко . Предыдущая версия .
Re[3]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 09:38
Оценка:
Здравствуйте, Videoman, Вы писали:

V>и её нельзя вызвать из Cи.


Разве я где-то упоминал Си?
Re[3]: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 23.01.23 09:51
Оценка: 1 (1) +1
Здравствуйте, Евгений Музыченко, Вы писали:

S>>без примеров кода однозначно понять что же вам нужно бывает затруднительно


ЕМ>В данном случае то, что мне нужно — отдельный вопрос.


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

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


Начать можно было бы с того, что в моей вселенной нет сигнатуры "шаблонной функции", как и нет такой штуки, как "шаблонная функция". А есть "шаблон функции", т.е. не функция, а некий шаблон, который превращается в функции в процессе определения параметров шаблона (т.е. в процессе инстанциирования). Соотвественно, если нет функции, то нет и сигнатуры.

PS. При этом я могу сильно ошибаться и в стандарте C++ все это может быть описано сильно другими словами, но такой взгляд на вещи сильно упрощает жизнь с C++.
Re[5]: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 23.01.23 10:00
Оценка: 1 (1)
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Там было конкретное описание действия: "явно определив версии с допустимыми комбинациями параметров".


Определить версии с допустимыми комбинациями параметров можно по-разному:
template<typename A, typename B>
void dummy(A a, B b) {
  static_assert((std::is_same_v<A, char> && std::is_same_v<B, int>)
    || (std::is_same_v<A, int> && std::is_same_v<B, float>)
    || (std::is_same_v<A, float> && std::is_same_v<B, long long>));

  ...
}

или
template<typename A, typename B>
void dummy(A a, B b);

template<>
void dummy(char a, int b) {...}

template<>
void dummy(int a, float b) {...}

template<>
void dummy(float a, long long b) {...}


ЕМ>"Инстанцирование" — это не термин, а уродливая калька для тех, кто мыслит не понятиями, а идентификаторами.


"Инстанцииорование" и "специализация" -- это вполне себе конкретные понятия, которые обозначают конкретные вещи. Часть общего словаря, на котором С++ разработчики доносят свои идеи до коллег. Использование устоявшихся терминов устраняет неоднозначности в толкованиях.
Re[3]: Для чего шаблонной функции нужна особая сигнатура?
От: Videoman Россия https://hts.tv/
Дата: 23.01.23 10:03
Оценка: 18 (1)
Здравствуйте, Евгений Музыченко, Вы писали:

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


Потому, что даже если мы имеем шаблон функции:
template <typename type_t>
void fun(const type_t* ptr)
{
// ...
}
то, вот это вот разные функции:
void fun(const char* ptr); // 1
template <>
void fun(const char* ptr); // 2

// ...

const char* ptr = "some string";

fun(ptr); // вызываем первую, у неё приоритет
fun<>(ptr); // вызываем вторую, явно указывая что хотим специализацию шаблона
Re[4]: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 23.01.23 10:13
Оценка:
Здравствуйте, Videoman, Вы писали:

V>[/ccode]то, вот это вот разные функции:
V>fun(ptr); // вызываем первую, у неё приоритет
V>fun<>(ptr); // вызываем вторую, явно указывая что хотим специализацию шаблона
V>


Его волнует проблема линковки:

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

К линковке приоритет выбора между шаблоном и обычной функцией не имеет отношения. Зато линкеру нужно повыбрасывать копии реализации шаблона функции с одинаковыми параметрами, созданными в разных единицах трансляции, а оставить только одну.
Re[3]: Для чего шаблонной функции нужна особая сигнатура?
От: σ  
Дата: 23.01.23 10:21
Оценка: +2
ЕМ>В данном случае то, что мне нужно — отдельный вопрос. Основной вопрос был о том, для чего сигнатура шаблонной функции отличается от сигнатуры перегруженной функции с той же комбинацией типов. Один из вариантов — для обеспечения приоритета. Еще могут быть какие-то основания?

Очевидно, для того, чтобы различать функции с одинаковым типом, но инстанциированные из разных шаблонов
template<typename T, typename U> void f(T, U); // 1
template<typename U, typename T> void f(T, U); // 2


int main()
{
    f<int, double>(0, 0.); // 1
    f<double, int>(0, 0.); // 2
}

(https://timsong-cpp.github.io/cppwp/n4659/temp.over.link#1)
Отредактировано 23.01.2023 13:01 σ . Предыдущая версия .
Re[4]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 10:26
Оценка:
Здравствуйте, so5team, Вы писали:

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


Да, в целом Ваше предположение верно — я хочу оставить в заголовке только перегруженные объявления, а шаблон спрятать в файл реализации (.cpp), поскольку так проще всего ограничить количество возможных вариантов, и не нарушать совместимости с другими библиотеками.

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

S>в моей вселенной нет сигнатуры "шаблонной функции", как и нет такой штуки, как "шаблонная функция". А есть "шаблон функции"


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

S>не функция, а некий шаблон


Или функция, которая является шаблонной — типовой, применимой к различным конкретным условиям.

S>если нет функции, то нет и сигнатуры.


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

S>в стандарте C++ все это может быть описано сильно другими словами


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

Но, зная, что есть люди, которым доставляет удовольствие чтение и обсуждение стандартов C++, не упускаю случая дать им возможность проявить себя.
Re[5]: Для чего шаблонной функции нужна особая сигнатура?
От: σ  
Дата: 23.01.23 10:39
Оценка: +1
ЕМ>Это достаточно странно, поскольку и в англоязычной, и в русскоязычной литературе термины "шаблон функции" и "шаблонная функция" вполне себе равнозначны, то же справедливо и для классов.

«function template» и «templated function» это-таки не одно и то же
Re[6]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 10:41
Оценка:
Здравствуйте, so5team, Вы писали:

S>Определить версии с допустимыми комбинациями параметров можно по-разному


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

S>"Инстанцииорование" и "специализация" -- это вполне себе конкретные понятия, которые обозначают конкретные вещи. Часть общего словаря, на котором С++ разработчики доносят свои идеи до коллег. Использование устоявшихся терминов устраняет неоднозначности в толкованиях.


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

"Специализация" — гораздо более давно устоявшийся термин для многих смыслов, он и к шаблонам подошел удачно.
Re[5]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 10:45
Оценка:
Здравствуйте, so5team, Вы писали:

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


Это обычно делается за счет того же механизма, который выбрасывает одинаковые константы (строки, GUID'ы/UUID'ы и т.п.), отдельных средств для этого не требуется. У MS для этого создается COMDAT.
Re[4]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 10:47
Оценка:
Здравствуйте, σ, Вы писали:

σ>
template<typename T, typename U> void f(T, U); // 1
template<typename U, typename T> void f(T, U); // 2


Хм, разве компилятор не считает это одним шаблоном с [возможно] различными специализациями?
Re[6]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 10:50
Оценка:
Здравствуйте, σ, Вы писали:

σ>«function template» и «templated function» это-таки не одно и то же


Ну так и я ж говорю о сигнатуре шаблонной функции, а не самого шаблона этой функции.
Re[5]: Для чего шаблонной функции нужна особая сигнатура?
От: Videoman Россия https://hts.tv/
Дата: 23.01.23 10:57
Оценка:
Здравствуйте, so5team, Вы писали:

S>Его волнует проблема линковки:

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

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

Сложно понять, что он хочет, поэтому даю всю релевантную инфу, не жалко, вдруг поможет .
Проблема линковки этих функций, это уже следствие. А выбрасывание-невыбрасывание, могут быть, могут не быть, зависит от линкера. Все оптимизации уже после происходят.
Re[7]: Для чего шаблонной функции нужна особая сигнатура?
От: σ  
Дата: 23.01.23 11:00
Оценка:
σ>>«function template» и «templated function» это-таки не одно и то же

ЕМ>Ну так и я ж говорю о сигнатуре шаблонной функции, а не самого шаблона этой функции.


Чо? Возьми определения signature из https://timsong-cpp.github.io/cppwp/n4659/intro.defs и покажи, про что ты
Re[5]: Для чего шаблонной функции нужна особая сигнатура?
От: σ  
Дата: 23.01.23 11:10
Оценка: +4
ЕМ>σ>
template<typename T, typename U> void f(T, U); // 1
template<typename U, typename T> void f(T, U); // 2

ЕМ>Хм, разве компилятор не считает это одним шаблоном

Хм, нет

ЕМ> с [возможно] различными специализациями?


Чо?
Re[5]: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 23.01.23 11:21
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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


ЕМ>Да, в целом Ваше предположение верно — я хочу оставить в заголовке только перегруженные объявления, а шаблон спрятать в файл реализации (.cpp), поскольку так проще всего ограничить количество возможных вариантов, и не нарушать совместимости с другими библиотеками.


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

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


Проблема в том, что вы используете формулировки, которые запросто можно трактовать по разному. И об этом вам только за последние 3-4 дня человек пять сказало.

S>>в моей вселенной нет сигнатуры "шаблонной функции", как и нет такой штуки, как "шаблонная функция". А есть "шаблон функции"


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


S>>не функция, а некий шаблон


ЕМ>Или функция, которая является шаблонной — типовой, применимой к различным конкретным условиям.


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

Шаблонная функция лучше подходит к языкам вроде Java и C#, в которых обобщенное программирование реализовано через генерики. Там код шаблонной функции можно скомпилировать однажды (даже без актуальных параметров), а затем использовать этот скомпилированный код при вызове функции с разными типами параметров.

S>>если нет функции, то нет и сигнатуры.


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


Если компилятор по шаблону сгенерировал результирующую функцию с фиксированным набором параметров то вполне логично, что у нее конечная сигнатура собственная, ни с чем не совпадающая.

Вас же не удивляет то, что
void f(int, int);
void f(long, long);

получают в итоге разные сигнатуры.
Re[7]: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 23.01.23 11:26
Оценка: 6 (1)
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Если нет, то какое это имеет значение для заданного вопроса?


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

S>>"Инстанцииорование" и "специализация" -- это вполне себе конкретные понятия, которые обозначают конкретные вещи. Часть общего словаря, на котором С++ разработчики доносят свои идеи до коллег. Использование устоявшихся терминов устраняет неоднозначности в толкованиях.


ЕМ>Так есть же устоявшийся термин — "создание экземпляра".


Создание экземпляра прежде всего ассоциируется во с этим:
struct demo {...};

demo obj; // Создали экземпляр.
demo * d = new demo; // И здесь создали экземпляр.


В случае с шаблонами принято говорить об инстанциировании шаблона.

Хороший это термин или нет здесь обсуждать смысла нет. Но, думается, участники дискуссии быстрее поймут что понимается под "инстанциированием", чем под "созданием экземпляра".
Re[6]: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 23.01.23 11:34
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Это обычно делается за счет того же механизма, который выбрасывает одинаковые константы (строки, GUID'ы/UUID'ы и т.п.), отдельных средств для этого не требуется. У MS для этого создается COMDAT.


Я понятия не имею как именно работают линкеры и какой именно формат у объектников, но здравый смысл подсказывает, что если у нас есть N объектников с дублями кода шаблона функции, то следует решить две проблемы:

a) как выбросить лишние дубли дабы они не раздували итоговый бинарник;
b) как поправить ссылки в коде на вызовы шаблона функций после того, как повыбрасывали дубли.

Соответственно, если у нас template<T>void f(T) для int превращается (условно) в __f_t_T_int, а void f(int) (условно) в __f_i, то мы легко можем понять где в коде нужно поменять ссылки на код шаблонной f (ищем вызовы __f_t_T_int), но не трогать ссылки на код нешаблонной f.

Если бы места вызова template<T> void f(T) для int не отличались бы от мест вызова void f(int), то как решать вторую проблему?
Re: Для чего шаблонной функции нужна особая сигнатура?
От: rg45 СССР  
Дата: 23.01.23 18:09
Оценка: 9 (1) +2
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Хотел в одной из библиотек сделать финт ушами: в заголовке оставить объявления нескольких одноименных функций с перегрузкой типов параметров, а в модуле реализовать их общим шаблоном, явно определив версии с допустимыми комбинациями параметров. По замыслу, это позволило бы линковать с ней другие библиотеки без перекомпиляции их исходников. Но оказалось, что [как минимум] VC++ дает шаблонным функциям сигнатуры, отличные от сигнатур обычных функций, и линковки таки не получается.




Какие сигнатуры дает функциям VC++ — это его личное дело, какие хочет, такие и дает. А то, что делаешь ты — это в заголовочном файле объявляешь одни функции, а в "модуле" другие. И эти последние, конечно же, не видны за пределами единицы трансляции, поскольку нигде больше не объявлены. Ты можешь вынести свои шаблонные функции в тот же заголовок и это будут просто отдельные функции. И все вместе они будут подчиняться правилам Overload resolution.

C++ предоставляет тебе возможность объявить/определить две функции, у которых будут одинаковые имена, количество и типы формальных параметров и типы возвращаемого значения — одну шаблонную, а другую нешаблонную, и только в этом будет их различие. Можно показать на примере семейства функций округления с различными методами:

http://coliru.stacked-crooked.com/a/20a19418d9506072

enum class RoundMethod
{
    Down,
    Up,
    Nearest,
    Default = Nearest
};

template<RoundMethod = RoundMethod::Default>
double Round(double);

double Round(double v) { return Round<>(v); }


И тогда будут одновременно доступны такие, например, формы вызова как Round(3.14), Round<>(3.14) и Round<RoundMethod::Default>(3.14). И при этом будут вызываться разные функции. Более того, одни из них могут вызывать другие!

Сколько времени, ты говоришь, программируешь на C++ — 42 года или 43? Очень странно, что приходится объяснять тебе такие азы.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 23.01.2023 19:07 rg45 . Предыдущая версия . Еще …
Отредактировано 23.01.2023 18:54 rg45 . Предыдущая версия .
Отредактировано 23.01.2023 18:52 rg45 . Предыдущая версия .
Отредактировано 23.01.2023 18:52 rg45 . Предыдущая версия .
Отредактировано 23.01.2023 18:51 rg45 . Предыдущая версия .
Отредактировано 23.01.2023 18:24 rg45 . Предыдущая версия .
Отредактировано 23.01.2023 18:22 rg45 . Предыдущая версия .
Re[2]: Для чего шаблонной функции нужна особая сигнатура?
От: σ  
Дата: 23.01.23 19:00
Оценка: +1 -1 :)
R>Сколько времени, ты говоришь, программируешь на C++ — 42 года или 43? Очень странно, что приходится объяснять тебе такие азы.
Прост уже деменция.
Re[8]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 19:07
Оценка:
Здравствуйте, σ, Вы писали:

ЕМ>>Ну так и я ж говорю о сигнатуре шаблонной функции, а не самого шаблона этой функции.


σ>Возьми определения signature из https://timsong-cpp.github.io/cppwp/n4659/intro.defs и покажи, про что ты


Я про function template specialization. С каким другим определением сигнатуры его можно спутать?
Re[6]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 19:22
Оценка:
Здравствуйте, so5team, Вы писали:

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


Ну так здесь "шаблон функции" и становится "шаблонной функцией" — функцией, сгенерированной по шаблону. "Шаблонный текст" — это конкретный текст, написанный по шаблону текста, "шаблонное поведение" — тоже конкретное поведение, реализующее шаблон поведения, и т.п.

S>Шаблонная функция лучше подходит к языкам вроде Java и C#, в которых обобщенное программирование реализовано через генерики. Там код шаблонной функции можно скомпилировать однажды (даже без актуальных параметров), а затем использовать этот скомпилированный код при вызове функции с разными типами параметров.


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

S>Вас же не удивляет то, что

S>
S>void f(int, int);
S>void f(long, long);
S>

S>получают в итоге разные сигнатуры.

Это как раз не удивляет. А вот о том, что можно смешивать шаблонные и нешаблонные функции с одинаковыми наборами типов, я давно и прочно забыл, поскольку никогда этим не пользовался. Только вот какой в этом может быть смысл? Разве только перекрыть ранее определенную нешаблонную функцию, но это ж получатся изрядные грабли.
Re[8]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 19:27
Оценка: -1
Здравствуйте, so5team, Вы писали:

S>Создание экземпляра прежде всего ассоциируется во с этим:

S>
S>demo * d = new demo; // И здесь создали экземпляр.
S>


S>В случае с шаблонами принято говорить об инстанциировании шаблона.


Это нарушает в первую очередь принцип единообразия терминологии. Исходный англоязычный термин instantiate применяется и к классу ("шаблону" объекта), и к шаблону класса, и к шаблону функции. Использование разных терминов в русском, из которых один переведен адекватно, а другой тупо транслитерирован — явный косяк.
Re[2]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 19:31
Оценка: :)
Здравствуйте, rg45, Вы писали:

R>Сколько времени, ты говоришь, программируешь на C++ — 42 года или 43?


28.

R>Очень странно, что приходится объяснять тебе такие азы.


Ничего странного. Я ж на C++ программирую, а не сдаю по нему экзамены или прохожу собеседования. Поэтому хорошо помню лишь то, чем пользуюсь, а задачи пользоваться всеми возможностями языка лишь для того, чтобы это продемонстрировать, у меня никогда не было. Сомневаюсь, что в обозримое время сумею с пользой применить возможность определить одновременно и шаблонную, и нешаблонную функцию с одинаковым набором типов.
Re[3]: Для чего шаблонной функции нужна особая сигнатура?
От: rg45 СССР  
Дата: 23.01.23 19:42
Оценка: :)
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Ничего странного. Я ж на C++ программирую, а не сдаю по нему экзамены или прохожу собеседования. Поэтому хорошо помню лишь то, чем пользуюсь, а задачи пользоваться всеми возможностями языка лишь для того, чтобы это продемонстрировать, у меня никогда не было. Сомневаюсь, что в обозримое время сумею с пользой применить возможность определить одновременно и шаблонную, и нешаблонную функцию с одинаковым набором типов.


Звучит примерно как: "Я ж машину вожу, а не сдаю экзамен по вождению. Поэтому помнить где педаль газа, а где тормоза мне не обязательно". Как можно после 28 лет использования языка не понимать его базовых принципов, это мне сложно постичь.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 20:41
Оценка:
Здравствуйте, rg45, Вы писали:

R>Звучит примерно как: "Я ж машину вожу, а не сдаю экзамен по вождению. Поэтому помнить где педаль газа, а где тормоза мне не обязательно".


Боюсь, более корявую аналогию придумать уже невозможно.

Во-первых, при вождении машины я всегда пользуюсь педалями газа и тормоза. За все время вождения не припомню ни одной поездки, в которой я сумел бы обойтись хотя бы одной.

Во-вторых, большинство профессиональных водителей знает формальные правила движения гораздо хуже, чем я — C++.

В-третьих, ежели Вас сейчас подвергнуть экзамену на знание всех тонкостей ПДД, то вряд ли Вы осилите сдать даже простенькие ПДД РФ, которые умещаются в тонкую книжицу, не говоря уже о каком-нибудь французском талмуде Code de Route, которого полностью, подозреваю, не знает вообще никто.

R>Как можно после 28 лет использования языка не понимать его базовых принципов


Элементарно, ибо это не "базовые принципы". Тем более, что я все эти годы успешно обходился без них.
Re[5]: Для чего шаблонной функции нужна особая сигнатура?
От: rg45 СССР  
Дата: 23.01.23 20:51
Оценка: :)
Здравствуйте, Евгений Музыченко, Вы писали:

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

ЕМ>...
ЕМ>Элементарно, ибо это не "базовые принципы". Тем более, что я все эти годы успешно обходился без них.

Умение объявить функцию — что уж может быть базовее. Умение находить педали газа и тормоза — навык примерно того же уровня. Так что аналогия — прямее некуда. А то, что ты сюда невпопад приплетаешь и другие понятия: сигнатуры, линковку, модули и пр. указывает на то, что ты не понимаешь ни первого, ни второго, ни третьего. И все это только усиливает впечатление. Это нужно какой-то специальный дар иметь — три десятка лет использовать язык и нифига о нем не знать вообще.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 23.01.2023 21:04 rg45 . Предыдущая версия . Еще …
Отредактировано 23.01.2023 21:01 rg45 . Предыдущая версия .
Отредактировано 23.01.2023 21:01 rg45 . Предыдущая версия .
Отредактировано 23.01.2023 20:55 rg45 . Предыдущая версия .
Re[6]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 21:44
Оценка:
Здравствуйте, rg45, Вы писали:

R>Умение объявить функцию — что уж может быть базовее.


Это Вы так изящно предположили, что мне за 28 лет ни разу не приходилось объявлять функции?

R>А то, что ты сюда невпопад приплетаешь и другие понятия: сигнатуры, линковку, модули и пр. указывает на то, что ты не понимаешь ни первого, ни второго, ни третьего.


Это сильно.
Re[7]: Для чего шаблонной функции нужна особая сигнатура?
От: rg45 СССР  
Дата: 23.01.23 21:53
Оценка: :)
Здравствуйте, Евгений Музыченко, Вы писали:


ЕМ>Это Вы так изящно предположили, что мне за 28 лет ни разу не приходилось объявлять функции?


Нет, это ВЫ в этой теме продемонстрировали свои навыки в этой области. А я просто оценил это зрелище.


R>>А то, что ты сюда невпопад приплетаешь и другие понятия: сигнатуры, линковку, модули и пр. указывает на то, что ты не понимаешь ни первого, ни второго, ни третьего.


ЕМ>Это сильно.


Как есть.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 23.01.2023 21:55 rg45 . Предыдущая версия . Еще …
Отредактировано 23.01.2023 21:54 rg45 . Предыдущая версия .
Re: Для чего шаблонной функции нужна особая сигнатура?
От: Pzz Россия https://github.com/alexpevzner
Дата: 23.01.23 21:54
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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


А C++ позволяет определить шаблонную функцию с некоторым именем и еще, отдельно, нешаблонную с тем же именем и с тем же набором параметров, который может быть у шаблонной функции?
Re[2]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.01.23 22:02
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>А C++ позволяет определить шаблонную функцию с некоторым именем и еще, отдельно, нешаблонную с тем же именем и с тем же набором параметров, который может быть у шаблонной функции?


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

P.S. Добро пожаловать в клуб не знающих <i>азов</i> языка С++
Автор: rg45
Дата: 23.01.23
.
Отредактировано 23.01.2023 22:06 Евгений Музыченко . Предыдущая версия .
Re[3]: Для чего шаблонной функции нужна особая сигнатура?
От: rg45 СССР  
Дата: 23.01.23 22:12
Оценка: :)
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Оказывается, позволяет. Не иначе, для каких-нибудь хитрых шаблонных побочек.


Какое удивительное открытие. И тридцати лет не прошло.

Я бы не стал писать сообщение по такому пустяковому поводу, просто в этом твоем высказывании скрывается ответ на твой же вопрос
Автор: Евгений Музыченко
Дата: 24.01.23
, приходилось ли тебе писать объявления функций или нет.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[7]: Для чего шаблонной функции нужна особая сигнатура?
От: пффф  
Дата: 23.01.23 22:16
Оценка: 1 (1)
Здравствуйте, Евгений Музыченко, Вы писали:

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


Просто назови это очередным костылем и успокойся


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


Только наоборот — нешаблонная перекрывает шаблонную. Никаких граблей, все с этим живут 30+ лет
Re[6]: Для чего шаблонной функции нужна особая сигнатура?
От: пффф  
Дата: 23.01.23 22:20
Оценка:
Здравствуйте, rg45, Вы писали:

R>Умение объявить функцию — что уж может быть базовее. Умение находить педали газа и тормоза — навык примерно того же уровня. Так что аналогия — прямее некуда. А то, что ты сюда невпопад приплетаешь и другие понятия: сигнатуры, линковку, модули и пр. указывает на то, что ты не понимаешь ни первого, ни второго, ни третьего. И все это только усиливает впечатление. Это нужно какой-то специальный дар иметь — три десятка лет использовать язык и нифига о нем не знать вообще.


Это понятно — он 30 лет пилит один продукт, вот и всё. Программистом со стажем его сложно назвать
Re[3]: Для чего шаблонной функции нужна особая сигнатура?
От: Pzz Россия https://github.com/alexpevzner
Дата: 23.01.23 22:21
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>P.S. Добро пожаловать в клуб не знающих <i>азов</i> языка С++
Автор: rg45
Дата: 23.01.23
.


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

Мои рабочие языки — это Си и Go.
Re[2]: Для чего шаблонной функции нужна особая сигнатура?
От: пффф  
Дата: 23.01.23 22:22
Оценка:
Здравствуйте, Pzz, Вы писали:

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


Pzz>А C++ позволяет определить шаблонную функцию с некоторым именем и еще, отдельно, нешаблонную с тем же именем и с тем же набором параметров, который может быть у шаблонной функции?


Без проблем. А что тут удивительного?
Re[3]: Для чего шаблонной функции нужна особая сигнатура?
От: Pzz Россия https://github.com/alexpevzner
Дата: 23.01.23 22:37
Оценка:
Здравствуйте, пффф, Вы писали:

Pzz>>А C++ позволяет определить шаблонную функцию с некоторым именем и еще, отдельно, нешаблонную с тем же именем и с тем же набором параметров, который может быть у шаблонной функции?


П>Без проблем. А что тут удивительного?


Я просто уточнил. Я не знаток этого языка.
Re[3]: Для чего шаблонной функции нужна особая сигнатура?
От: rg45 СССР  
Дата: 24.01.23 01:23
Оценка: +1
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>P.S. Добро пожаловать в клуб не знающих <i>азов</i> языка С++
Автор: rg45
Дата: 23.01.23
.


Так а он нигде и не заявляет о свомем многолетнем опыте в этой области. Ни с кем не спорит и не требует переделать язык под себя, как ты. У тебя же что ни тема, то стенания по поводу того, какой плохой инструмент разработки тебе достался. А ты бы познакомился с этим инструментом для начала, хоть мало-мальски, а потом бы спорил уже.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 24.01.2023 1:34 rg45 . Предыдущая версия . Еще …
Отредактировано 24.01.2023 1:33 rg45 . Предыдущая версия .
Отредактировано 24.01.2023 1:28 rg45 . Предыдущая версия .
Отредактировано 24.01.2023 1:27 rg45 . Предыдущая версия .
Отредактировано 24.01.2023 1:26 rg45 . Предыдущая версия .
Отредактировано 24.01.2023 1:25 rg45 . Предыдущая версия .
Отредактировано 24.01.2023 1:24 rg45 . Предыдущая версия .
Re[7]: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 24.01.23 05:23
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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


ЕМ>Ну так здесь "шаблон функции" и становится "шаблонной функцией" — функцией, сгенерированной по шаблону. "Шаблонный текст" — это конкретный текст, написанный по шаблону текста, "шаблонное поведение" — тоже конкретное поведение, реализующее шаблон поведения, и т.п.


Шаблон функции -- это как шаблон для заготовки. Вы берете шаблон и по шаблону изготавливаете деталь, далее используется уже конкретная деталь, а не шаблон.

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

Поэтому в C++ имея шаблон:
template<typename T, typename U> void f(T a, U b);

вы в результате раскрытия шаблона (в зависимости от типов T и U) можете получить как:
void f(T1 a, U1 b) { a.f(b); }

так и:
void f(T2 a, U2 b) { b.g(a); }

так и:
void f(T3 a, U3 b) { a.f(); b.g(); }

так и:
void f(T4, U4) {}

и т.д.

А вот шаблонная функция в языках с генериками какой была, такой и останется. Например (псевдокод):
void F<T, U>(T a, U b) where A : IHasFMethod { a.f(b); }


ЕМ>Только вот какой в этом может быть смысл?


Такой же, как в перегрузке вообще. Такой же, как и в наличии специализации для шаблонов.
Re[9]: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 24.01.23 05:25
Оценка: 1 (1) +2
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Это нарушает в первую очередь принцип единообразия терминологии. Исходный англоязычный термин instantiate применяется и к классу ("шаблону" объекта), и к шаблону класса, и к шаблону функции. Использование разных терминов в русском, из которых один переведен адекватно, а другой тупо транслитерирован — явный косяк.


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

PS. Вот честно давно уже считал себя ярким подтверждением актуальности афоризма "старого пса новым трюкам не обучишь", но, думается, вы здесь можете дать мне приличную фору.
Re[7]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.01.23 08:46
Оценка:
Здравствуйте, пффф, Вы писали:

П>он 30 лет пилит один продукт


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

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


В чем выгода от использования чистого C по сравнению с разумным подмножеством C++?
Re[4]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.01.23 09:00
Оценка:
Здравствуйте, rg45, Вы писали:

R>У тебя же что ни тема, то стенания по поводу того, какой плохой инструмент разработки тебе достался.


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

R>ты бы познакомился с этим инструментом для начала, хоть мало-мальски


Уговорили — сегодня же начну изучать классы. Я про них что-то слышал — пора уже и познакомиться поближе.
Re[8]: Для чего шаблонной функции нужна особая сигнатура?
От: σ  
Дата: 24.01.23 09:22
Оценка: :)
П>>он 30 лет пилит один продукт

ЕМ>Нет.


Даже одного не пилит?
Отредактировано 24.01.2023 9:23 σ . Предыдущая версия .
Re[8]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.01.23 09:25
Оценка:
Здравствуйте, so5team, Вы писали:

S>Шаблон функции -- это как шаблон для заготовки. Вы берете шаблон и по шаблону изготавливаете деталь, далее используется уже конкретная деталь, а не шаблон.


Совершенно верно. И называются такие изделия "шаблонными": составленные по шаблону, по модели — строго держась ея, сделанный по шаблону, связанный, соотносящийся по значению с существительным "шаблон"

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


То есть — конкретный результат раскрытия шаблона. Шаблон функции — семейство возможных вариантов функции, шаблонная функция — один из членов этого семейства.

ЕМ>>Только вот какой в этом может быть смысл?


S>Такой же, как в перегрузке вообще. Такой же, как и в наличии специализации для шаблонов.


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

Вообще, все это выглядит очень забавно на фоне нападок на обычную перегрузку C++ — "как можно иметь функции с одинаковыми именами, но разным поведением?!".
Re[10]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.01.23 09:34
Оценка:
Здравствуйте, so5team, Вы писали:

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


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

Кстати, русским языком я пользуюсь уже больше пятидесяти лет, и гораздо чаще, чем C++, и когда-то делал это профессионально (писал заказные статьи для журналов), однако не сумею сделать синтаксический разбор более-менее сложного предложения, а уж типа спряжения не назову ни для одного глагола. И да, мне тоже не стыдно...
Re[9]: Для чего шаблонной функции нужна особая сигнатура?
От: so5team https://stiffstream.com
Дата: 24.01.23 09:45
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

S>>Шаблон функции -- это как шаблон для заготовки. Вы берете шаблон и по шаблону изготавливаете деталь, далее используется уже конкретная деталь, а не шаблон.


ЕМ>Совершенно верно.


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

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


ЕМ>То есть — конкретный результат раскрытия шаблона.


Нет. Посмотрите на приведенные мной примеры. В C++ вы можете иметь разные конкретные результаты применения шаблона функции. Т.е. разный код. Компилятор обрабатывает шаблон и делает функцию, далее результирующая функция делает конкретные действия.

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

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

S>>Такой же, как в перегрузке вообще. Такой же, как и в наличии специализации для шаблонов.


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


Бла-бла-бла. Это все херня и очень странно, что вы этого не видите не смотря на 40+ лет в программировании.

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

Если эта задача наилучшим образом решается перегрузкой, то она решается перегрузкой. Если шаблонами -- то шаблонами (включая специализации для них).

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


Достаточно вспомнить, что шаблоны в язык добавили сильно позже того, как язык стал мейнстримом. Так что одна из целей того, что у обычных функций есть приоритет над шаблонными, -- это обеспечение той же самой логики работы кода, который был написан до появления шаблонов, при переходе на более свежие версии языка.
Re[5]: Для чего шаблонной функции нужна особая сигнатура?
От: rg45 СССР  
Дата: 24.01.23 10:08
Оценка: 9 (1) :)
Здравствуйте, Евгений Музыченко, Вы писали:

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


Ура, вот и на нашей улице праздник, теперь Евгений начнет писать на C с классами.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[10]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.01.23 10:45
Оценка:
Здравствуйте, so5team, Вы писали:

S>В C++ вы можете иметь разные конкретные результаты применения шаблона функции. Т.е. разный код.


Этот код привязан к общему шаблону, или нет? Функции, полученные в результате реализации/специализации шаблона, как-то связаны между собой, или они полностью независимы?

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


Сравнение с другими языками имеет смысл лишь в плане философского обсуждения. Если Вы считаете, что термин "template function" неприменим к C++ — возражайте Страуструпу, Александреску, Майерсу и прочим корифеям, которые употребляют его регулярно.

S>Если эта задача наилучшим образом решается перегрузкой, то она решается перегрузкой. Если шаблонами -- то шаблонами (включая специализации для них).


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

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


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

S>>В C++ вы можете иметь разные конкретные результаты применения шаблона функции. Т.е. разный код.


ЕМ>Этот код привязан к общему шаблону, или нет? Функции, полученные в результате реализации/специализации шаблона, как-то связаны между собой, или они полностью независимы?


Сложение a и b удовлетворяют общему шаблону или нет? Реализации сложения a и b полностью независимы?

ЕМ>Сравнение с другими языками имеет смысл лишь в плане философского обсуждения.


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

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


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

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


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

Кроме того, здесь мы явно имеем ситуацию, когда приоритет нужно отдать либо одному (скажем, обычным функциям), либо другому (скажем, шаблонам). И какой бы выбор не был сделан, всегда найдется кто-то с бородой до пола, который заявит, а я в программировании 40 лет, никогда подобной фигни не видел и не понимаю, почему так, объясните мне!
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 . Предыдущая версия .
Re[7]: Для чего шаблонной функции нужна особая сигнатура?
От: Pzz Россия https://github.com/alexpevzner
Дата: 26.01.23 11:23
Оценка: +1
Здравствуйте, Евгений Музыченко, Вы писали:

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


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


К сожалению, как только код становится не твоим личным, и появляется хоть какая-то совместная разработка, используемое подмножество языка имеет тенденцию бесконтролько разрастаться.
Re[7]: Для чего шаблонной функции нужна особая сигнатура?
От: Pzz Россия https://github.com/alexpevzner
Дата: 26.01.23 11:25
Оценка:
Здравствуйте, σ, Вы писали:

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


σ>Для Си тоже могут быть нужны должностные инструкции. А то есть компиляторы с __attribute__((cleanup(...))) и прочими приятными дополнениями.


Лучше всего, конечно, иметь не должностную инструкцию, а тулзу, которая не дает использовать лишнего. Но увы, Си плохо потдается тулингу...
Re[8]: Для чего шаблонной функции нужна особая сигнатура?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 26.01.23 12:13
Оценка:
Здравствуйте, Pzz, Вы писали:

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


Поэтому я всю жизнь успешно избегаю совместной разработки.
Re[8]: Для чего шаблонной функции нужна особая сигнатура?
От: пффф  
Дата: 26.01.23 17:10
Оценка:
Здравствуйте, Pzz, Вы писали:

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


Pzz>К сожалению, как только код становится не твоим личным, и появляется хоть какая-то совместная разработка, используемое подмножество языка имеет тенденцию бесконтролько разрастаться.


Даже в эмбеде для пылесосов в этом нет проблемы
Re[8]: Для чего шаблонной функции нужна особая сигнатура?
От: пффф  
Дата: 26.01.23 17:12
Оценка:
Здравствуйте, Pzz, Вы писали:

σ>>Для Си тоже могут быть нужны должностные инструкции. А то есть компиляторы с __attribute__((cleanup(...))) и прочими приятными дополнениями.


Pzz>Лучше всего, конечно, иметь не должностную инструкцию, а тулзу, которая не дает использовать лишнего. Но увы, Си плохо потдается тулингу...


Что, и на базе clang'а ничего нельзя натулить? По твоей логике, плюсы вообще невозможно натулить, ведь они почти всё сишечное вобрали и сверху вагон с тележкой
Re[9]: Для чего шаблонной функции нужна особая сигнатура?
От: Pzz Россия https://github.com/alexpevzner
Дата: 26.01.23 20:48
Оценка:
Здравствуйте, пффф, Вы писали:

Pzz>>К сожалению, как только код становится не твоим личным, и появляется хоть какая-то совместная разработка, используемое подмножество языка имеет тенденцию бесконтролько разрастаться.


П>Даже в эмбеде для пылесосов в этом нет проблемы


Так это ж проблема не пылесосов, а программистов. Пылесосу-то все равно.
Re[2]: Для чего шаблонной функции нужна особая сигнатура?
От: rg45 СССР  
Дата: 26.01.23 21:11
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Зададимся вопросом: существует ли такой код, для которого этот вызов не будет вызовом функции template<> void f<>(char* p);?

BFE>Я, таки, напишу это: не всё так однозначно!

Как раз в данном случае все однозначно, ответ: существует. Вот три варианта, которые выиграют overload resolution — при любом объявлении primary template:

void f(char*);
void f(char* &);
void f(char* const &);


Правда первый создает коллизию с двумя другими, но это не важно в данном случае. Главное, что все три выигрывают у специализации. Еще раз подчеркну, при любом объявлении основного шаблона (совместимом с приведенной специализацией, разумеется).
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 26.01.2023 21:23 rg45 . Предыдущая версия . Еще …
Отредактировано 26.01.2023 21:21 rg45 . Предыдущая версия .
Отредактировано 26.01.2023 21:13 rg45 . Предыдущая версия .
Отредактировано 26.01.2023 21:13 rg45 . Предыдущая версия .
Re[3]: Для чего шаблонной функции нужна особая сигнатура?
От: B0FEE664  
Дата: 27.01.23 16:09
Оценка:
Здравствуйте, rg45, Вы писали:

R>Правда первый создает коллизию с двумя другими, но это не важно в данном случае. Главное, что все три выигрывают у специализации. Еще раз подчеркну, при любом объявлении основного шаблона (совместимом с приведенной специализацией, разумеется).


Такое впечатление, что вы не поняли ни вопроса Евгений Музыченко, ни моего ответа на него. Ну или не дочитали...
Суть в том, что вызов f(p); не вызывает функцию template<> void f<>(char* p); даже если используются исключительно шаблонные функции.
И каждый день — без права на ошибку...
Re: концепты?
От: Sm0ke Россия ksi
Дата: 27.01.23 16:42
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Хотел в одной из библиотек сделать финт ушами: в заголовке оставить объявления нескольких одноименных функций с перегрузкой типов параметров, а в модуле реализовать их общим шаблоном, явно определив версии с допустимыми комбинациями параметров. По замыслу, это позволило бы линковать с ней другие библиотеки без перекомпиляции их исходников. Но оказалось, что [как минимум] VC++ дает шаблонным функциям сигнатуры, отличные от сигнатур обычных функций, и линковки таки не получается.


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


template <typename T, typename ... V>
concept c_any_of = ( std::is_same_v<T, V> || ... );

template <c_any_of<int, double> T>
void func(T number) {}


Это поможет? Тут лишь 20-ый стандарт
Отредактировано 27.01.2023 16:43 Sm0ke . Предыдущая версия .
Re: Для чего шаблонной функции нужна особая сигнатура?
От: vopl Россия  
Дата: 27.01.23 17:05
Оценка: 9 (1)
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Хотел в одной из библиотек сделать финт ушами: в заголовке оставить объявления нескольких одноименных функций с перегрузкой типов параметров, а в модуле реализовать их общим шаблоном, явно определив версии с допустимыми комбинациями параметров. По замыслу, это позволило бы линковать с ней другие библиотеки без перекомпиляции их исходников.


А вообще, такой финт вполне можно делать и со специализациями, не обязательно брать именно не-шаблонные функции

hdr.h — публичный заголовок
#pragma once

//#define MY_API __declspec(dllimport)
#define MY_API __attribute__((visibility("default")))

template <class> void MY_API mySuperPuperFunction();


impl.cpp — реализация, в библиотеке
//#define MY_API __declspec(dllexport)
#define MY_API __attribute__((visibility("default")))

template <class> void MY_API mySuperPuperFunction()
{
    // код
}

// явно определив версии с допустимыми комбинациями параметров
template void mySuperPuperFunction<int>();
template void mySuperPuperFunction<char>();


use.cpp — использование, в приложении, надо прилинковать библиотеку
#include <hdr.h>

int main()
{
    mySuperPuperFunction<int>();//ок
    mySuperPuperFunction<char>();//ок
    mySuperPuperFunction<short>();//не ок, ошибка линковки
    return 0;
}
Отредактировано 27.01.2023 17:13 vopl . Предыдущая версия .
Re[2]: Для чего шаблонной функции нужна особая сигнатура?
От: σ  
Дата: 27.01.23 17:12
Оценка: 1 (1) +1
V>
// явно определив версии с допустимыми комбинациями параметров
template <> void mySuperPuperFunction<int>();
template <> void mySuperPuperFunction<char>();

template void mySuperPuperFunction<int>();
template void mySuperPuperFunction<char>();
Re[4]: Для чего шаблонной функции нужна особая сигнатура?
От: rg45 СССР  
Дата: 27.01.23 21:00
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Такое впечатление, что вы не поняли ни вопроса Евгений Музыченко, ни моего ответа на него. Ну или не дочитали...


Так и есть. Вопрос не понял, ответ не дочитал. Потому что ответ длинный, а вопрос непонятный. По ответу можно еще как-то догадываться о смысле вопроса, но как тебе удалось распарсить оригинал — это для меня непостижимо. При чем там линковка Люди с котлетами, мухи с попугаями.

P.S. Ну и вдогонку, то, что ты написал, можно было выразить одним предложением: overload resolution выполняется по primary template объявлениям, игнорируя специализации. Связь же с ***ВОПРОСОМ*** по-преженему остается для меня загадкой.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 27.01.2023 21:20 rg45 . Предыдущая версия . Еще …
Отредактировано 27.01.2023 21:07 rg45 . Предыдущая версия .
Отредактировано 27.01.2023 21:06 rg45 . Предыдущая версия .
Re[4]: Для чего шаблонной функции нужна особая сигнатура?
От: rg45 СССР  
Дата: 27.01.23 21:33
Оценка: 2 (1) +1
Здравствуйте, B0FEE664, Вы писали:

BFE>Суть в том, что вызов f(p); не вызывает функцию template<> void f<>(char* p); даже если используются исключительно шаблонные функции.


Я вам еще этюд "в тему" подброшу, так, чтоб у сипипи-фобов припадок случился. Вот вам два примера:

http://coliru.stacked-crooked.com/a/f4573e39736257ab

  1
#include <iostream>

template <typename T>
void foo(T) { std::cout << 0 << std::endl; }

template <typename T>
void foo(T*) { std::cout << 1 << std::endl; }

template <>
void foo<char*>(char*) { std::cout << 2 << std::endl; }

int main()
{
    char* p{};
    foo(p); // -> 1
}


http://coliru.stacked-crooked.com/a/d22d3b584cb6a6aa

  2
#include <iostream>

template <typename T>
void foo(T) { std::cout << 0 << std::endl; }

template <typename T>
void foo(T*) { std::cout << 1 << std::endl; }

template <>
void foo<char>(char*) { std::cout << 2 << std::endl; }

int main()
{
    char* p{};
    foo(p); // -> 2
}


Первый выводит "1", а второй выводит "2". Задача: найдите ОДНО отличие.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 28.01.2023 10:07 rg45 . Предыдущая версия . Еще …
Отредактировано 28.01.2023 9:36 rg45 . Предыдущая версия .
Отредактировано 27.01.2023 21:34 rg45 . Предыдущая версия .
Re[2]: концепты?
От: Кодт Россия  
Дата: 05.04.23 19:18
Оценка: 9 (1) +1
Здравствуйте, Sm0ke, Вы писали:

В 20 (ну и в 23) стандарте есть недосказанность, а в C++ ABI популярных компиляторов (gcc / clang / msvc), соответственно, есть БАГ, эксплуатирующий эту недосказанность.
А именно, ограничения (концепты и requires) не попадают в декорированные имена.

Из-за этого можно написать well-formed программу, в которой сам же компилятор нарушит ODR: даст двум разным функциям один и тот же символ линковки.
А потом сойдёт с ума сам (если проинлайнит) или сведёт с ума линкер.

template<class T> void foo() { printf("1"); }

template<class T> void bar() { foo<T>(); }  // в этой точке видна только foo #1, поэтому она и вызовется

template<class T> void foo() requires true { printf("2"); }

template<class T> void buz() { foo<T>(); }  // функция с ограничением имеет приоритет, поэтому вызовется foo #2

int main() {
  bar<void>();
  buz<void>();
}
// для разнообразия, попробуйте разнести объявления и определения foo
// и перетащить определения выше-ниже точки инстанцирования, то есть, main().


...думаете вы!

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

Мейнтейнеры gcc сперва два года отбивались, говоря, что это ill-formed no diagnostics required и чего вы хотите, а потом взяли паузу на год и вот буквально месяц или два назад признали, что это баг.

А поскольку этот баг затрагивает спецификацию ABI, то его исправление приведёт к поломке огромного количества уже скомпилированных библиотек.
Так что, тут хоть закапывай, хоть выкапывай стюардессу, но раньше 2026 года он исправлен не будет.

Ну и кстати, возвращаясь к исходной теме про шаблоны.
MSVC по этим граблям сходил в 1998 году, когда ещё концептов не было.
Разработчики компилятора верили, что параметры шаблона всегда влияют на сигнатуру функции. (А иначе зачем нужно было шаблон писать? Г — Логика!)
template<class T> void foo();  // тип функции - один и тот же: void()

int main() {
  foo<int>();
  foo<char>(); // фигушки, линкер всё равно возьмёт foo<int>
}

и исправили его в 2005 году.
А до того народ лайфхачил как мог: добавлял невидимые аргументы, засовывал функции внутрь шаблона класса.

Но микрософту было хорошо, они хозяева своей экосистемы, взяли и заявили о несовместимости MSVC 7 и 8, пересобрали все виндовые библиотеки, и готово.

А гусь со шлангом так уже не могут!
Перекуём баги на фичи!
Re[3]: концепты?
От: vopl Россия  
Дата: 06.04.23 12:11
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Sm0ke, Вы писали:


К>В 20 (ну и в 23) стандарте есть недосказанность, а в C++ ABI популярных компиляторов (gcc / clang / msvc), соответственно, есть БАГ, эксплуатирующий эту недосказанность.

К>А именно, ограничения (концепты и requires) не попадают в декорированные имена.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100825
https://github.com/llvm/llvm-project/issues/49884
https://github.com/itanium-cxx-abi/cxx-abi/issues/24
Re[4]: концепты?
От: Кодт Россия  
Дата: 06.04.23 12:50
Оценка:
Здравствуйте, vopl, Вы писали:


К>>В 20 (ну и в 23) стандарте есть недосказанность, а в C++ ABI популярных компиляторов (gcc / clang / msvc), соответственно, есть БАГ, эксплуатирующий эту недосказанность.

К>>А именно, ограничения (концепты и requires) не попадают в декорированные имена.

V>https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100825

V>https://github.com/llvm/llvm-project/issues/49884
V>https://github.com/itanium-cxx-abi/cxx-abi/issues/24

Угу, оно самое. В гусёвом трекере даже моё имя присутствует.
Перекуём баги на фичи!
Re[4]: концепты?
От: Кодт Россия  
Дата: 08.04.23 23:03
Оценка: +1
Здравствуйте, vopl, Вы писали:

V>https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100825#c14


Richard Smith 2023-04-07 19:50:08 UTC
I've proposed mangling rules on the ABI list: https://github.com/itanium-cxx-abi/cxx-abi/issues/24#issuecomment-1491130332

We're ready to land an implementation in Clang; I would appreciate feedback from GCC folks first, though.


Так что грядёт фикс!
Перекуём баги на фичи!
Re[7]: Для чего шаблонной функции нужна особая сигнатура?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 09.04.23 00:26
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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


Нешаблонные функции наоборот имеют больший приоритет
Маньяк Робокряк колесит по городу
Re[11]: Для чего шаблонной функции нужна особая сигнатура?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 09.04.23 00:34
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:


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


Шаблонные функции по типам параметров не могут совпадать полностью с перегруженными функциями. По определению. Полностью совпадать могут, если ты сделал специализацию шаблонной функции, которая по типам параметров будет совпадать с перегруженной функцией. Не уверен, но мне кажется, что в таком случае будет варнинг или даже ошибка


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


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


Синдром поиска голубиного смысла? Чем тебе не нравится банальное сохранение совместимости? Слишком простой ответ?
Маньяк Робокряк колесит по городу
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.