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...
Пока на собственное сообщение не было ответов, его можно удалить.