Cоздание базового шаблона минуя специализацию
От: Videoman Россия https://hts.tv/
Дата: 25.10.22 21:45
Оценка:
Возможен ли сабж в принципе? Что-то туплю. Хочется примерно следующего:
#include <iostream>

template <typename type_t>
struct object
{
    void print() { std::cout << "base template"; }
};

template <>
struct object<int>
{
    void print() { std::cout << "specialized template"; }
};

int main()
{
    object<int> obj; // force base template here
    obj.print();

    return 0;
}
Временно отменить специализацию и создать базовый вариант шаблона для int-а, что бы код выдал: "base template".

Задачка неожиданно возникла во время игр с std::format. Ребята в комитете придумали, что кастомные форматеры, это специализации классов. Ну сделал я специализацию для своего класса, который тоже является специализацией библиотечного шаблона. А как мне теперь вызвать реализацию по умолчанию для базового шаблона ? Или я что-то не то делаю
http://www.gravatar.com/avatar/60560936caa07b944d4c3cecf1c06cc5?s=80&d=identicon
Re: Cоздание базового шаблона минуя специализацию
От: _niko_ Россия  
Дата: 26.10.22 06:36
Оценка:
Здравствуйте, Videoman, Вы писали:

V> Ну сделал я специализацию для своего класса

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

struct base_api
{
  void print() { std::cout << "base template"; }
};

template <typename type_t>
struct object : base_api
{
  ...
};

template <>
struct object<int> : base_api
{
    void print() { std::cout << "specialized template"; }
};

int main()
{
    object<int> obj;
    obj.base_api::print();

    return 0;
}


Но все же
obj.base_api::print();
— это говорит о том что тут что то пошло не так и лучше бы перепроектировать
Re[2]: Cоздание базового шаблона минуя специализацию
От: Videoman Россия https://hts.tv/
Дата: 26.10.22 07:23
Оценка:
Здравствуйте, _niko_, Вы писали:

__>...


__>Но все же
obj.base_api::print();
— это говорит о том что тут что то пошло не так и лучше бы перепроектировать




Это же не я, это стандартная библиотека такую свинью подложила, std. Вот эти вот классы, они в std определены и специализировать мне их предлагают по стандарту. А я говорил, что люди принимающие стандарты, по ходу вообще не думают, последнее время.
Конструктивная критика: почему они сделали классы, почему не функции, как это сделал я в свое время в своей библиотеке форматирования. Если сделать форматер для всех наследников какого-то класса еще можно, с помощью SFINAE, то ADL для специализаций классов не работает и нет возможности определять форматеры в своём пространстве имен, оставляя возможность вызывать базовые из std.
http://www.gravatar.com/avatar/60560936caa07b944d4c3cecf1c06cc5?s=80&d=identicon
Re: Cоздание базового шаблона минуя специализацию
От: rg45 СССР  
Дата: 26.10.22 11:08
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Возможен ли сабж в принципе? Что-то туплю. Хочется примерно следующего:[ccode]

V>Временно отменить специализацию и создать базовый вариант шаблона для int-а, что бы код выдал: "base template".

Вот прямо в такой формулировке, думаю, что невозможен — потому что в таком случае возникает две различные версии одной и той же специализации, а это нарушение ODR. Нужно думать, какие тут можно костыли прикрутить.
--
Завтра сегодня будет вчера
Re[2]: Cоздание базового шаблона минуя специализацию
От: Videoman Россия https://hts.tv/
Дата: 26.10.22 11:54
Оценка:
Здравствуйте, rg45, Вы писали:

R>Вот прямо в такой формулировке, думаю, что невозможен — потому что в таком случае возникает две различные версии одной и той же специализации, а это нарушение ODR. Нужно думать, какие тут можно костыли прикрутить.


Наверное вопрос в этом, как выкрутится теперь. Ситуация простая. У std::formatter есть специализация для вывода std::chrono::duration<>. У меня в библиотеках везде используется своя специализация времени:
using reftime_t = std::chrono::duration<int64, std:ratio<1, 10000000>>;
Стандартные возможности форматирования огромны, но мне хочется их расширить для своего типа времени и переиспользовать. Таким образом объявляя
template <>
struct std::formatter<reftime_t> {
    // ...
};
я автоматически лишаюсь возможности вызвать стандартную реализацию и вынужден повторять всю логику заново. Это не дело, я считаю
http://www.gravatar.com/avatar/60560936caa07b944d4c3cecf1c06cc5?s=80&d=identicon
Re[3]: Cоздание базового шаблона минуя специализацию
От: so5team https://stiffstream.com
Дата: 26.10.22 12:18
Оценка: +1
Здравствуйте, Videoman, Вы писали:

V>Наверное вопрос в этом, как выкрутится теперь. Ситуация простая. У std::formatter есть специализация для вывода std::chrono::duration<>. У меня в библиотеках везде используется своя специализация времени:
V>using reftime_t = std::chrono::duration<int64, std:ratio<1, 10000000>>;
V>


Поскольку в C++ нет strong typedef, то компилятор C++ не может отличить ваш reftime_t от каких-либо других алиасов для std::chrono::duration.

ИМХО, тут напрашивается одно из двух:

— либо вы делаете свой reftime_t таки strong typedef-ом для std::chrono::duration, чтобы это был именно что другой тип на уровне C++. И тогда делаете для своего типа нужную вам специализацию std::formatter (наследуясь от std::formatter<std::chrono::duration<...>>);

— либо вы делаете обертку для своего reftime_t:

struct reftime_for_std_format_t {
  reftime_t val_;
};

[[nodiscard]]
inline reftime_for_std_format_t wrap(reftime_t v) { return { v }; }


Затем пишете для reftime_for_std_format_t специализацию std::formatter. И отображаете свои значения reftime_t посредством wrap:
std::format("Duration is {}", wrap(your_reftime_value));


И тот, и другой способы геморройные. Разве что для первого способа можно задействовать какую-то готовую библиотеку с реализацией strong typedef.
Re[3]: Cоздание базового шаблона минуя специализацию
От: σ  
Дата: 26.10.22 12:38
Оценка:
V>Это же не я, это стандартная библиотека такую свинью подложила, std. Вот эти вот классы, они в std определены и специализировать мне их предлагают по стандарту.

Да вроде в std нельзя добавлять специализаций, не зависящих от program-defined type (https://timsong-cpp.github.io/cppwp/n4868/namespace.std#2)
Re[4]: Cоздание базового шаблона минуя специализацию
От: Videoman Россия https://hts.tv/
Дата: 26.10.22 15:44
Оценка:
Здравствуйте, σ, Вы писали:

σ>Да вроде в std нельзя добавлять специализаций, не зависящих от program-defined type (https://timsong-cpp.github.io/cppwp/n4868/namespace.std#2)


Специализации определённых в std шаблонов добавлять можно. Нельзя добавлять свои новые имена.

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

http://www.gravatar.com/avatar/60560936caa07b944d4c3cecf1c06cc5?s=80&d=identicon
Re[4]: Cоздание базового шаблона минуя специализацию
От: Videoman Россия https://hts.tv/
Дата: 26.10.22 15:51
Оценка:
Здравствуйте, so5team, Вы писали:

S>И тот, и другой способы геморройные. Разве что для первого способа можно задействовать какую-то готовую библиотеку с реализацией strong typedef.


Всё это очевидно. Тут больше вопросы к тем, кто принимает какое в std.
Свою проблему я решил, т.к. оказывается, что всю работу делает специализация formatter<std::time_t> и все вызовы в итоге приводят туда, а любой chrono тип приводится к time_t. Но это просто везение. А что делать, если это не так, по прежнему остается загадкой. С таким дизайном стандартной библиотеки, будем надеяться, что стандартных форматеров хватит всем, на все случаи жизни.
http://www.gravatar.com/avatar/60560936caa07b944d4c3cecf1c06cc5?s=80&d=identicon
Отредактировано 26.10.2022 15:52 Videoman . Предыдущая версия .
Re[5]: Cоздание базового шаблона минуя специализацию
От: so5team https://stiffstream.com
Дата: 26.10.22 16:05
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Тут больше вопросы к тем, кто принимает какое в std.


Если вы хоте вести речь в таком тоне, то позвольте встречный вопрос: а что лично вы сделали, чтобы в стандарт попало что-то более вменяемое?
Re[6]: Cоздание базового шаблона минуя специализацию
От: Videoman Россия https://hts.tv/
Дата: 26.10.22 17:17
Оценка: +2
Здравствуйте, so5team, Вы писали:

S>Если вы хоте вести речь в таком тоне, то позвольте встречный вопрос: а что лично вы сделали, чтобы в стандарт попало что-то более вменяемое?


Ответ на это вопрос выходит за рамки топика. Не знаю что вам не нравится в тоне. Конструктивную критику я уже высказал: т.к. у меня была реализация точно такого же функционала с точно таким же синтаксисом, но она была построена на функциях, т.к. к ним применим ADL, а с ним возможна кастомизация форматирования для каждого конкретного неймспейса. Давайте лучше заниматься каждый своим делом, но желательно так, что бы те кто пользуются этими результатами не страдали, а были довольны тем, как замечательно мы с вами все за них продумали.
http://www.gravatar.com/avatar/60560936caa07b944d4c3cecf1c06cc5?s=80&d=identicon
Re[5]: Cоздание базового шаблона минуя специализацию
От: σ  
Дата: 26.10.22 17:22
Оценка:
σ>>Да вроде в std нельзя добавлять специализаций, не зависящих от program-defined type (https://timsong-cpp.github.io/cppwp/n4868/namespace.std#2)

V>Специализации определённых в std шаблонов добавлять можно. Нельзя добавлять свои новые имена.

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

И шо, std::chrono::duration<int64, std:ratio<1, 10000000>> удовлетворяет условию (а)?
Re[6]: Cоздание базового шаблона минуя специализацию
От: Videoman Россия https://hts.tv/
Дата: 26.10.22 17:39
Оценка:
Здравствуйте, σ, Вы писали:

σ>И шо, std::chrono::duration<int64, std:ratio<1, 10000000>> удовлетворяет условию (а)?


Да согласен, слишком упростил пример. У меня на самом деле перекрывается специализация std::chrono::time_point<reference_clock>, где reference_clock уже точно мой класс.
http://www.gravatar.com/avatar/60560936caa07b944d4c3cecf1c06cc5?s=80&d=identicon
Re[7]: Cоздание базового шаблона минуя специализацию
От: rg45 СССР  
Дата: 26.10.22 19:05
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Конструктивную критику я уже высказал: т.к. у меня была реализация точно такого же функционала с точно таким же синтаксисом, но она была построена на функциях, т.к. к ним применим ADL, а с ним возможна кастомизация форматирования для каждого конкретного неймспейса.


Поддерживаю всеми руками.
--
Завтра сегодня будет вчера
Re[3]: Cоздание базового шаблона минуя специализацию
От: σ  
Дата: 26.10.22 20:06
Оценка:
V>Конструктивная критика: почему они сделали классы, почему не функции, как это сделал я в свое время в своей библиотеке форматирования. Если сделать форматер для всех наследников какого-то класса еще можно, с помощью SFINAE, то ADL для специализаций классов не работает и нет возможности определять форматеры в своём пространстве имен, оставляя возможность вызывать базовые из std.

Да вроде ответ гуглится.
Re[4]: Cоздание базового шаблона минуя специализацию
От: Videoman Россия https://hts.tv/
Дата: 26.10.22 20:49
Оценка:
Здравствуйте, σ, Вы писали:

σ>Да вроде ответ гуглится.


Может и гуглится, но мне вот не попадалось. Как с таким подходом как в std сделать свою кастомизацию форматирования int, например?
http://www.gravatar.com/avatar/60560936caa07b944d4c3cecf1c06cc5?s=80&d=identicon
Re[5]: Cоздание базового шаблона минуя специализацию
От: σ  
Дата: 26.10.22 21:52
Оценка: +1
V>Как с таким подходом как в std сделать свою кастомизацию форматирования int, например?

А как через ADL сделать?
Re[7]: Cоздание базового шаблона минуя специализацию
От: so5team https://stiffstream.com
Дата: 27.10.22 04:53
Оценка: +1
Здравствуйте, Videoman, Вы писали:

S>>Если вы хоте вести речь в таком тоне, то позвольте встречный вопрос: а что лично вы сделали, чтобы в стандарт попало что-то более вменяемое?


V>Ответ на это вопрос выходит за рамки топика.


А вот это все еще в рамках топика?

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


V>Не знаю что вам не нравится в тоне.


Поведение в стиле "вот у меня все было по уму, а в std включили хз что"

V>Конструктивную критику я уже высказал: т.к. у меня была реализация точно такого же функционала с точно таким же синтаксисом, но она была построена на функциях, т.к. к ним применим ADL, а с ним возможна кастомизация форматирования для каждого конкретного неймспейса.


И где здесь критика? Я не увидел ни ссылки на исходники вашей библиотеки, в которой можно было бы посмотреть на альтернативный подход. Ни описания деталей этого подхода здесь. Более того, здесь видно как вы сами путаетесь в показаниях, т.к. у вас сперва reftime_t -- это синоним для стандартного std::chrono::duration, а потом оказывается, что все несколько не так.

Конструктивная критика должна, как минимум, идти в https://stdcpp.ru/

Здесь же наблюдается какое-то брюзжание из категории "меня не спросили".

std::format взялся не на пустом месте. Много лет в OpenSource была fmtlib, автор которой потратил туеву хучу времени и сил на то, чтобы выложить это в OpenSource, снабдить документацией, среагировать на огромное количество issues, принять кучу pull-request-ов, выслушать в свой адрес всякое-разное. А потом еще и принять участие в формировании предложения в стандарт, и пройти вместе с другими соавторами через процесс включения в стандарт.

Причем процесс включения в стандарт был открытым, высказывать свои замечания/предложения к предложению можно было еще до того, как std::format стандартизировали.

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

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

И тут не суть важно, была ли у вас такая цель и желание, или не было. Ситуация с тем, что попадает в стандарт C++, проста: кто приложил усилия, тот и добился (или нет). И так оно уже лет 30, можно было бы и привыкнуть.
Re[8]: Cоздание базового шаблона минуя специализацию
От: Videoman Россия https://hts.tv/
Дата: 27.10.22 09:09
Оценка:
Здравствуйте, so5team, Вы писали:

S>Конструктивная критика должна, как минимум, идти в https://stdcpp.ru/

Если все программисты будут сидеть на stdcpp.ru, то кто и когда будет делать всё остальное. Искренне считаю, что то, что вы предлагаете, постоянно сидеть на форуме С++ и мониторить все предложения, анализировать их и проверять — не возможно на практике.

S>Здесь же наблюдается какое-то брюзжание из категории "меня не спросили".

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

S>std::format взялся не на пустом месте. Много лет в OpenSource была fmtlib, автор которой потратил туеву хучу времени и сил на то, чтобы выложить это в OpenSource, снабдить документацией, среагировать на огромное количество issues, принять кучу pull-request-ов, выслушать в свой адрес всякое-разное. А потом еще и принять участие в формировании предложения в стандарт, и пройти вместе с другими соавторами через процесс включения в стандарт.

Знаем знаем как всё там не на пустом месте. Ребята из Microsoft запилили библиотеку для своих личных нужд и пропихнули её в стандарт, т.к. могли.

S>Причем процесс включения в стандарт был открытым, высказывать свои замечания/предложения к предложению можно было еще до того, как std::format стандартизировали.

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

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

Я прекрасно понимаю что такое решение получено в процессе консенсуса. Оно вообще по результату может полностью не устраивать все стороны которые его, вроде бы, принимали. Но зачем так яростно его защищать, даже если там есть очевидные недостатки
http://www.gravatar.com/avatar/60560936caa07b944d4c3cecf1c06cc5?s=80&d=identicon
Re[6]: Cоздание базового шаблона минуя специализацию
От: Videoman Россия https://hts.tv/
Дата: 27.10.22 09:14
Оценка:
Здравствуйте, σ, Вы писали:

V>>Как с таким подходом как в std сделать свою кастомизацию форматирования int, например?


σ>А как через ADL сделать?


Как такое сделать дня базовых типов я не знаю. А можно кто-то в комитете продумает за меня ?!. В своём решении я, во всяком случае, могу это сделать. Для остальных классов можно хотя бы дать возможность не подключать заголовки стандартных форматеров, а использовать свои.
http://www.gravatar.com/avatar/60560936caa07b944d4c3cecf1c06cc5?s=80&d=identicon
Отредактировано 27.10.2022 9:16 Videoman . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.