Как расширить std::formatter, не создавая иногда конфликтов (могут ли концепции при повторной оценке позже в программе вC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Как расширить std::formatter, не создавая иногда конфликтов (могут ли концепции при повторной оценке позже в программе в

Сообщение Anonymous »

Я знаю, как специализироваться std::formatter; с явной специализацией это относительно просто и понятно.
Но с частичной специализацией - это проблема - из-за меняющегося характера различных библиотек (включая стандартную библиотеку C++) и того, какие частичные специализации уже включены (а иногда даже детали внедрения того, как они реализованы - только то, что они совпадают).
У меня есть библиотека с кучей предоставленных типов, которая пытается работать с различными std версии C++ (20, 23, 26) и эти типы работают с форматтером.
Из Стройки 'ToString.h'

Код: Выделить всё

// Does type 'T' support the Stroika ToString() API
template 
concept IToString = requires (T t) { { ToString (t) } -> convertible_to; };
...
template 
struct ToStringFormatter /* : std::formatter*/{...}
Тогда я хочу сказать что-то вроде: если стандартный форматтер еще не определен,
тогда используйте ToStringFormatter (не говоря уже о пространствах имен для простоты):

Код: Выделить всё

template 
requires (!std::formattable && IToString)
struct std::formatter : ToStringFormatter {};
Поэтому, если тип еще не форматируем, отформатируйте его с помощью ToStringFormatter.
Похоже, что это самый простой и естественный подход, но это не так. работайте над Visual Studio
(ошибка C7608: атомарное ограничение должно быть постоянным выражением)
предположительно потому, что определение фактически меняет значение, возвращаемое ограничением.
ИЛИ< /p>

Код: Выделить всё

template 
struct std::formatter : ToStringFormatter {};
Проблема второго подхода заключается в том, что он вносит неоднозначность, если используется с типом T, который является ОБА IToString и форматируемым.
Итак, я остановились на специальном подходе:

Код: Выделить всё

template 
concept IUseToStringFormatterForFormatter_ =
// most user-defined types captured by this rule - just add a ToString() method!
requires (T t) {
{
t.ToString ()
} -> convertible_to;
}

// Stroika types not captured by std-c++ rules
or Common::IKeyValuePair or Common::ICountedValue

// c++ 23 features which may not be present with current compilers
// value with clang++16 was 202101L and cpp2b and libc++ (ubuntu 23.10 and 24.04) flag...  and it had at least the pair code supported.
// this stuff needed for clang++-18-debug-libstdc++-c++23
#if !__cpp_lib_format_ranges
#if !qHasFeature_fmtlib or (FMT_VERSION < 110000)
or (ranges::range and
not Configuration::IAnyOf)
#endif
#endif

// sadly MSFT doesn't support all, and doesn't support __cplusplus with right value
// 202302L is right value to check for C++ 23, but 202101L needed for clang++16 ;-(
#if _MSC_VER || __cplusplus < 202101L /*202302L 202100L 202300L*/ || (__clang__ != 0 && __GLIBCXX__ != 0 && __GLIBCXX__ 

Подробнее здесь: [url]https://stackoverflow.com/questions/78774217/how-to-extend-stdformatter-without-sometimes-introducing-conflicts-can-concep[/url]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»