Re[21]: Cоздание базового шаблона минуя специализацию
От: so5team https://stiffstream.com
Дата: 28.10.22 07:43
Оценка:
Здравствуйте, rg45, Вы писали:

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


Так дьявол-то в деталях. А без деталей получается как в анекдоте "мыши, станьте ежиками!"

R>На примеры сейчас времени не хватает, сорри.


Вряд ли в этом вопросе кто-то куда-то торопится.
Re[20]: Cоздание базового шаблона минуя специализацию
От: rg45 СССР  
Дата: 28.10.22 08:19
Оценка: +1
Здравствуйте, so5team, Вы писали:

R>>Как частный случай — форматтер, определенный для базового класса автоматом будет работать и для всех производных, для которых не предоставлена своя собственая версия форматтера;


S>Это вроде как и сейчас в fmtlib возможно (полагаю, что и в std::format). Пример прямо из документации к fmtlib:


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

P.S. И виртуальность вы напрасно сюда внесли, имхо. Я изначально вел речь про обычное невиртуальное использование форматирования и виртуальность здесь вносит только лишний повод для побочных дискуссий.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 28.10.2022 8:22 rg45 . Предыдущая версия .
Re[22]: Cоздание базового шаблона минуя специализацию
От: rg45 СССР  
Дата: 28.10.22 08:38
Оценка:
Здравствуйте, so5team, Вы писали:

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

S>Так дьявол-то в деталях. А без деталей получается как в анекдоте "мыши, станьте ежиками!"
R>>На примеры сейчас времени не хватает, сорри.
S>Вряд ли в этом вопросе кто-то куда-то торопится.

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

Примеры постараюсь предоставить, но чуть попозже.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[21]: Cоздание базового шаблона минуя специализацию
От: so5team https://stiffstream.com
Дата: 28.10.22 08:46
Оценка:
Здравствуйте, rg45, Вы писали:

R>Но если в будущем появляется еще и тип C, также производный от A, и вы попытаетесь написать для него форматтер, похожий на тот, который уже написали для A, вы тут же почувствуете неудобство — этого нельзя будет сделать, не модифицировав специализацию форматтера для A, потому что обе специализации окажутся равноправны и создадут коллизию. Этого не произошло бы с функциями.


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

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

Не пытаясь защищать fmtlib и std::format (мне процедура написания собственных специализаций formatter-а кажется неудобной) все же есть ощущение, что в процессе эволюции fmtlib и прохождение через комитет наверняка высказывались самые разные идеи, а на практике выжила имеющаяся комбинация возможностей + сложность реализации + накладные расходы.

R>P.S. И виртуальность вы напрасно сюда внесли, имхо.


Пример из документации к fmtlib, я его просто скопипастил. Все претензии к Зверовичу.
Re[22]: Cоздание базового шаблона минуя специализацию
От: rg45 СССР  
Дата: 28.10.22 08:56
Оценка:
Здравствуйте, so5team, Вы писали:

S>Это вообще зыбкая почва для споров. Если мы оперируем традиционным полиморфизмом, то надобность в отдельном форматтере для C вызывает вопросы.


Да, только этих вопросов даже не возникло бы в случае использования функций. Может, для начала стоит ответить на вопрос, почему вместо фунций необходимо использовать шаблон класса? Имхо, прикладная библиотека не должна диктовать разработчику вопросы дизайна. Тем более в области "зыбких почв"
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 28.10.2022 9:08 rg45 . Предыдущая версия . Еще …
Отредактировано 28.10.2022 9:02 rg45 . Предыдущая версия .
Re[23]: Cоздание базового шаблона минуя специализацию
От: so5team https://stiffstream.com
Дата: 28.10.22 09:13
Оценка:
Здравствуйте, rg45, Вы писали:

S>>Это вообще зыбкая почва для споров. Если мы оперируем традиционным полиморфизмом, то надобность в отдельном форматтере для C вызывает вопросы.


R>Да только этих вопросов даже не возникло бы в случае использования функций.


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

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

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


Были бы функции, можно было бы ответить. Но их нет.

У fmt::formatter, например, может быть состояние. Т.е. в процессе работы fmt::formatter::parse можно что-то сохранить/вычислить, что затем будет использовано в fmt::formatter::format. Причем наличие/отсутствие состояния совершенно прозрачно для самого fmt::format/print.

Тогда как функции stateless, и если из parse нужно что-то передать в format, то здесь уже нужно озадачиваться тем, чтобы функции были парными. Условно:
void parse(parsing_ctx &);
void format(const T & v, formatting_ctx &);

some_state parse(parsing_ctx &);
void format(const some_state & state, const T & v, formatting_ctx &);


И для меня не очевидно, что свободные функции в массовом применении в таком случае будут проще в использовании, чем специализации fmt::formatter.

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


Простите, но это уже демагогия. Любой существующий инструмент будет накладывать на пользователя какие-то ограничения. И с этим придется считать, возможно, и на уровне дизайна.
Re[24]: Cоздание базового шаблона минуя специализацию
От: rg45 СССР  
Дата: 28.10.22 09:57
Оценка:
Здравствуйте, so5team, Вы писали:

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

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

То есть, если я вижу какие-то конкретные минусы какой-то конкретной библиотеки, я не имею права об этом рассуждать до тех пор, пока не предоставлю рабочую альтернативу? Не жестковата ли постановка вопроса?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[24]: Cоздание базового шаблона минуя специализацию
От: rg45 СССР  
Дата: 28.10.22 10:11
Оценка:
Здравствуйте, so5team, Вы писали:

S>Тогда как функции stateless, и если из parse нужно что-то передать в format, то здесь уже нужно озадачиваться тем, чтобы функции были парными. Условно:

S>И для меня не очевидно, что свободные функции в массовом применении в таком случае будут проще в использовании, чем специализации fmt::formatter.

А для меня это полностью очевидно. В случае с функциями, для стандартной библиотеки вообще не составит труда поддержать передачу состояния, причем сделать это опционально — поддержать stateless/statеfull тем же самым путем, как осуществить пооддержку свободных функций, так и функций-членов. Да, это дополнительные телодвижения, но они делаются один раз внутри стандартной библиотеки. С точки зрения пользователя все получается удобно и комфортно. Да нужно будет обеспечивать консистентность пользовательских parse и формат, но для этого совсем не обязательно делать из всегда парными. И это гораздо удобнее, чем карячить специализации классов с конфликтами, разрывами неймспейсов и мозгов.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 28.10.2022 10:15 rg45 . Предыдущая версия .
Re[19]: Cоздание базового шаблона минуя специализацию
От: Went  
Дата: 28.10.22 10:34
Оценка: :))
Здравствуйте, rg45, Вы писали:
R>Так о том и речь, что их нет, а вместо функций — шаблон класса std::formatter. А если бы std::format для кастомизации использовал бы не шаблон класса со специализациями, а неквалифицированный вызов функции с каким-то предопределенным именем, это могло бы дать ряд преимуществ...
Наверное, я ошибаюсь, но все-таки спрошу. А нет ли опасности, что перегрузки этой функции — форматтера, объявленные после определения функции std::format, окажутся вне области её видимости и не будут вызываться? Или есть способ как-то просто обойти эту проблему?
Re[20]: Cоздание базового шаблона минуя специализацию
От: rg45 СССР  
Дата: 28.10.22 10:44
Оценка: 4 (1)
Здравствуйте, Went, Вы писали:

W>Наверное, я ошибаюсь, но все-таки спрошу. А нет ли опасности, что перегрузки этой функции — форматтера, объявленные после определения функции std::format, окажутся вне области её видимости и не будут вызываться? Или есть способ как-то просто обойти эту проблему?


Как я догадываюсь, твой вопрос уходит корнями в ту проблему, которую ты описывал здесь: http://rsdn.org/forum/cpp/7906979.1
Автор: Went
Дата: 16.12.20
?

Только в том случае у тебя возникли проблемы со встроенными типами. С типами, определенными пользователем, таких проблем не будет, ADL исправно будет работать. Равно как и для типов, в которых пользовательские типы фигурируют в качестве шаблонных параметров (std::vector<MyClass> и т.п.). Ну если только не косячить с неймспейсами, разумеется.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 28.10.2022 10:45 rg45 . Предыдущая версия .
Re[20]: Cоздание базового шаблона минуя специализацию
От: Videoman Россия https://hts.tv/
Дата: 28.10.22 11:14
Оценка: +1
Здравствуйте, Went, Вы писали:

W>Наверное, я ошибаюсь, но все-таки спрошу. А нет ли опасности, что перегрузки этой функции — форматтера, объявленные после определения функции std::format, окажутся вне области её видимости и не будут вызываться? Или есть способ как-то просто обойти эту проблему?


Сейчас также все не сахар. Форматер в виде специализации класса не вызывается и всё, пока ты правильно не подберёшь синтаксис перегрузки. С шаблонными классами это бывает не очень просто. Вот пример у меня в коде:
namespace htlib::v2
{
template<typename type_t>
struct is_point {

    static std::false_type test(...);
    template<htlib::v2::uint_t dimensions, typename other_t>
    static std::true_type test(const htlib::v2::pointxd_t<dimensions, other_t>&);

    static constexpr bool value = decltype(test(std::declval<type_t>()))::value;
};
template<typename type_t>
inline constexpr bool is_point_v = is_point<type_t>::value;

} // namespace htlib::v2

template<typename char_t, typename point_t>
class std::formatter<point_t, char_t, std::enable_if_t<htlib::v2::is_point_v<point_t>>>
{
//...
}
Вот такие мета-функции приходится писать что бы написать форматер для всех наследников базового шаблонного класса.

Хотя в случае с функциями была простая перегрузка, типа:
template<htlib::v2::uint_t dimensions, typename other_t>
void formatter(const htlib::v2::pointxd_t<dimensions, other_t>&);
Re[25]: Cоздание базового шаблона минуя специализацию
От: so5team https://stiffstream.com
Дата: 28.10.22 11:35
Оценка:
Здравствуйте, rg45, Вы писали:

R>То есть, если я вижу какие-то конкретные минусы какой-то конкретной библиотеки, я не имею права об этом рассуждать до тех пор, пока не предоставлю рабочую альтернативу? Не жестковата ли постановка вопроса?


Только такая постановка вопроса позволяет вести конструктивный разговор, сорри.

Просто сказать, что дизайн со специализацией formatter -- говно, а те, кто его стандартизировал, сделали это неподумавши, -- это лишь выпустить пар в свисток. Ибо нет никакого способа исправить ситуацию.

То, что можно сделать лучше, чем в fmt/std::format, с точки зрения теории, не подлежит сомнению. Но интересна не теория, а практика: как это будет выглядеть, сколько будет стоить.
Re[25]: Cоздание базового шаблона минуя специализацию
От: so5team https://stiffstream.com
Дата: 28.10.22 11:38
Оценка:
Здравствуйте, rg45, Вы писали:

R>С точки зрения пользователя все получается удобно и комфортно.


Раз.

R>Да нужно будет обеспечивать консистентность пользовательских parse и формат,


Два.

Только мне кажется, что "два" противоречит "раз"?

R>но для этого совсем не обязательно делать из всегда парными.


А какой в этом смысл?

R>И это гораздо удобнее, чем карячить специализации классов с конфликтами, разрывами неймспейсов и мозгов.


Разрый неймспейса -- да, серьезное неудобство. Регулярно на это чертыхаюсь.

Примеры конфликтов можно?
Re[26]: Cоздание базового шаблона минуя специализацию
От: Videoman Россия https://hts.tv/
Дата: 28.10.22 12:02
Оценка:
Здравствуйте, so5team, Вы писали:

S>Только мне кажется, что "два" противоречит "раз"?


Зачем нужно две функции, в том числе в текущей реализации fmt, понятно. Функция форматирования работает на этапе компиляции, т.е. она constexpr и выдает ошибки там же.
На самом деде не проблема сlелать static_assert с выдачей ошибки в случае отсутствия одной из функций. Увидели тип, какой-то функции нет — тут же static_assert.

S>Разрый неймспейса -- да, серьезное неудобство. Регулярно на это чертыхаюсь.


Разрыв неймспейса, это как раз специализация форматтер-а в пространстве имен std. Со свободными функциями это не нужно. Описываете функцию в своём же пространстве имен, ADL её найдет сам.
Re[27]: Cоздание базового шаблона минуя специализацию
От: so5team https://stiffstream.com
Дата: 28.10.22 12:15
Оценка:
Здравствуйте, Videoman, Вы писали:

S>>Только мне кажется, что "два" противоречит "раз"?


V>Зачем нужно две функции, в том числе в текущей реализации fmt, понятно. Функция форматирования работает на этапе компиляции, т.е. она constexpr и выдает ошибки там же.

V>На самом деде не проблема сlелать static_assert с выдачей ошибки в случае отсутствия одной из функций. Увидели тип, какой-то функции нет — тут же static_assert.

Э... А зачем вы это все написали? Это типа доказательство удобства иметь две свободные функции, которые пользователю нужно держать согласованными?
Re[26]: Cоздание базового шаблона минуя специализацию
От: rg45 СССР  
Дата: 28.10.22 12:23
Оценка: +1
Здравствуйте, so5team, Вы писали:

R>>С точки зрения пользователя все получается удобно и комфортно.


S>Раз.


R>>Да нужно будет обеспечивать консистентность пользовательских parse и формат,


S>Два.


S>Только мне кажется, что "два" противоречит "раз"?


А по-моему, совсем нет, если требуется состояние, то его нужно вернуть из parse, и получить в format параметром, если не нужно, значит ничего этого не нужно. Что может быть проще и естественнее?

S>Разрый неймспейса -- да, серьезное неудобство. Регулярно на это чертыхаюсь.


Так о чем и речь. Одно это перевешивает все остальное.

S>Примеры конфликтов можно?


Об одном случае я уже упоминал выше
Автор: rg45
Дата: 28.10.22
, вот эти две специализации одновременно могут подходить для одних и тех же типов:

template <typename T>
struct fmt::formatter<T, std::enable_if_t<std::is_base_of<A, T>::value, char>> {};

template <typename T>
struct fmt::formatter<T, std::enable_if_t<std::is_base_of<С, T>::value, char>> {};


И важно то, что проблема не сводится к одному лишь наследованию и не решается отказом от него. Я уверен многим из присутствующих приходилось разруливать самые разнообразные SFINAE-коллизии в виду того, что для одного типа подходят более одной специализации. Для функций этот вопрос во многих случаях реашется проще, благодаря механизму выбора кандидата, обеспечивающего лучшее соответствие типов формальных и фактических параметров. А при использовании SFINAE при специализации классов, фильтры нужно "полировать" при расширении, чтоб исключить накладки. Да я уверен, что вы и сами знаете об этой проблеме.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[27]: Cоздание базового шаблона минуя специализацию
От: so5team https://stiffstream.com
Дата: 28.10.22 12:34
Оценка:
Здравствуйте, rg45, Вы писали:

S>>Только мне кажется, что "два" противоречит "раз"?


R>А по-моему, совсем нет, если требуется состояние, то его нужно вернуть из parse, и получить в format параметром, если не нужно, значит ничего этого не нужно. Что может быть проще и естественнее?


Как раз подход с классом, у которого есть методы. Хотим, делаем состояние. Хотим не делаем. Хотим, делаем в зависимости от defines и фазы Луны. При этом прототипы самих методов не меняются.

При этом, в моей практике, при специализации fmt::formatter можно наследоваться от уже существующего fmt::formatter и переопределять только один из методов.

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

S>>Разрый неймспейса -- да, серьезное неудобство. Регулярно на это чертыхаюсь.


R>Так о чем и речь. Одно это перевешивает все остальное.


Э... Ну, ОК.

S>>Примеры конфликтов можно?


R>Об одном случае я уже упоминал выше
Автор: rg45
Дата: 28.10.22
, вот эти две специализации одновременно могут подходить для одних и тех же типов:


Т.е. пример а) искусственный и b) спорный.

Videoman привел свой пример из той же оперы. Но есть у меня ощущение, что там что-то человек сам перемудрил. Впрочем, могу ошибаться, чтобы убедиться в этом нужно глубоко в его код погрузиться.
Re[28]: Cоздание базового шаблона минуя специализацию
От: rg45 СССР  
Дата: 28.10.22 12:36
Оценка:
Здравствуйте, so5team, Вы писали:

S>А в случае функций нужно писать две функции.


Совсем не обязательно. Об этом я уже писал.

S>Т.е. пример а) искусственный и b) спорный.


Т.е. то, что написано после примера, вы проигнорировали. Ну ОК.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[29]: Cоздание базового шаблона минуя специализацию
От: so5team https://stiffstream.com
Дата: 28.10.22 12:39
Оценка:
Здравствуйте, rg45, Вы писали:

R>Т.е. то, что написано после примера, вы проигнорировали. Ну ОК.


Простите, общие слова не интересны. Конкретные примеры -- да, абстрактные рассуждения о том, как у кого-то где-то что-то -- нет.
Re[30]: Cоздание базового шаблона минуя специализацию
От: rg45 СССР  
Дата: 28.10.22 12:43
Оценка:
Здравствуйте, so5team, Вы писали:

S>Простите, общие слова не интересны. Конкретные примеры -- да, абстрактные рассуждения о том, как у кого-то где-то что-то -- нет.


А чего вы решаете за всех что интересно, что нет? Это ж форум, а не личная переписка.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 28.10.2022 12:43 rg45 . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.