Здравствуйте, rg45, Вы писали:
R>То есть, мы враппим std:/fmt:: format и дальше пользуемся только своим my::format. А formatter специализируем только один раз и пишем его так, что он делегирует вызовы пользовательским функциям с использованием ADL. Пожалуй, это будет работать, причем, даже для встроенных типов. Только для встроенных типов нужно будет заимплементить соответствующие функции в глобальном пространстве имен, причем так, чтоб их объявления (как минимум) были видны из нашей единственной специализации форматтера. Правильно я понял идею?
Не совсем. Всё так, но не понятно зачем в глобальном пространстве, когда можно в локальном. Класс диспетчера-то наш и мы вольны вызывать что хотим.
R>Один нюанс: необходимость определения функций в глобальном пространстве имен для встроенных типов будет диктовать выбор каких-то достаточно оригинальных имен для этих функций, чтобы исключить возможность нечаянных коллизий. Другой способ решения этой проблемы: добавление какого-нибудь фиктивного параметра, имеющего тип, определенный в пространстве имен my. При таком подходе имена для функций можно будет выбрать максимально простые и комфортные и перенести определения самих функций из глобального пространства имен в пространство имен my (это только для встроенных типов — для пользовательских типов функции можно будет спокойно определять в том же пространстве имен, что и сами типы).
Опять не понимаю. Зачем это делать в глобальном пространстве, можно ведь:
// dispatch formatter
template<typename char_t, typename type_t>
class fmt::formatter<my::wrapper<type_t>, char_t>
{
public:
constexpr auto parse(basic_format_parse_context<char_t>& ctx) -> decltype(ctx.begin())
{
return my::parse(...);
}
template<typename it_t>
auto format(my::wrapper<type_t>& data, basic_format_context<it_t, char_t>& ctx) const -> decltype(ctx.out())
{
return my::format(...);
}
};
// or
template<typename char_t, typename type_t>
class fmt::formatter<my::wrapper<type_t>, char_t>
{
my::formatter<type_t, char_t> m_formatter;
public:
constexpr auto parse(basic_format_parse_context<char_t>& ctx) -> decltype(ctx.begin())
{
return m_formatter.parse(...);
}
template<typename it_t>
auto format(my::wrapper<type_t>& data, basic_format_context<it_t, char_t>& ctx) const -> decltype(ctx.out())
{
return m_formatter.format(...);
}
};
и пустить свои иерархии объектов или функций в своём пространстве имен. Я не описываю делали сейчас. Просто указываю на точку кастомизации, из которой всё можно перенести в свой неймспейс и там уже делать кастомизацию или вызывать дефолтные реализации std, если нужно.