Как отформатировать указатели с помощью библиотеки fmt?

Я отвечаю на некоторые вопросы и заглядываю в библиотеку fmt: http://fmtlib.net/

Похоже, что у меня есть нужные мне функции и поддержка %p (указатель), но при компиляции моего кода, который использует%p, я получаю длинную строку ошибок шаблона (непонятно). Я опубликую их в конце этого.

если я вытащу %p и соответствующий аргумент указателя, затем он компилируется в VS2017 C++17.

Тем не менее, я в растерянности относительно того, как декодировать ошибки шаблона или получить некоторое представление о том, почему он не принимает %p аргумент в первую очередь.

Я пытался привести аргумент к (void*) - та же проблема.
Я попытался использовать синтаксис стиля Python в форматере {} - та же проблема.
Я разбил биты%p отдельно от остальной части форматирования - та же проблема.

Я вижу, что есть поддержка пользовательских типов - но в этом случае я просто хочу вывести это как необработанное значение указателя. Я мог бы просто пропустить это, ведь насколько ценным может быть адрес указателя? Но, конечно, это означает больше работы во время преобразования из sprintf в fmt::format выследить всех%p и "сделать что-нибудь с ними", например, исключить их.

Но документы, кажется, указывают, что%p поддерживается - http://fmtlib.net/latest/syntax.html (примерно 3/4 пути вниз - поиск по "указателю" или "p").

Вот вызывающая функция: (примечание: pAccels объявлен как const ACCEL *)

    m_hAccel = ::CreateAcceleratorTable(const_cast<LPACCEL>(pAccels), (int)count);
    if (!m_hAccel)
    {
        auto error = GetLastError();
        throw CWinAPIErrorException(__FUNCTION__, "CreateAcceleratorTable", fmt::format("%p,%u", pAccels, count), error);
    }

Вот диагностическое извержение:

1>c:\users\steve\source\fmt\include\fmt\core.h(1073): error C2825: 'fmt::v5::internal::get_type<Context,Arg>::value_type': must be a class or namespace when followed by '::'
1>        with
1>        [
1>            Context=fmt::v5::basic_format_context<std::back_insert_iterator<fmt::v5::internal::buffer<char>>,char>,
1>            Arg=const ACCEL *
1>        ]
1>c:\users\steve\source\fmt\include\fmt\core.h(1081): note: see reference to class template instantiation 'fmt::v5::internal::get_type<Context,Arg>' being compiled
1>        with
1>        [
1>            Context=fmt::v5::basic_format_context<std::back_insert_iterator<fmt::v5::internal::buffer<char>>,char>,
1>            Arg=const ACCEL *
1>        ]
1>c:\users\steve\source\fmt\include\fmt\core.h(1190): note: see reference to function template instantiation 'unsigned __int64 fmt::v5::internal::get_types<Context,const ACCEL*,size_t>(void)' being compiled
1>        with
1>        [
1>            Context=fmt::v5::basic_format_context<std::back_insert_iterator<fmt::v5::internal::buffer<char>>,char>
1>        ]
1>c:\users\steve\source\fmt\include\fmt\core.h(1190): note: while compiling class template member function 'unsigned __int64 fmt::v5::format_arg_store<fmt::v5::basic_format_context<std::back_insert_iterator<fmt::v5::internal::buffer<Char>>,Char>,const ACCEL *,size_t>::get_types(void)'
1>        with
1>        [
1>            Char=char
1>        ]
1>c:\users\steve\source\fmt\include\fmt\core.h(1478): note: see reference to class template instantiation 'fmt::v5::format_arg_store<fmt::v5::basic_format_context<std::back_insert_iterator<fmt::v5::internal::buffer<Char>>,Char>,const ACCEL *,size_t>' being compiled
1>        with
1>        [
1>            Char=char
1>        ]
1>c:\users\steve\source\tbx\wapi\acceleratortable.cpp(58): note: see reference to function template instantiation 'std::basic_string<char,std::char_traits<char>,std::allocator<char>> fmt::v5::format<char[6],const ACCEL*,size_t,0>(const S (&),const ACCEL *const &,const size_t &)' being compiled
1>        with
1>        [
1>            S=char [6]
1>        ]
1>c:\users\steve\source\fmt\include\fmt\core.h(1073): error C2510: 'value_type': left of '::' must be a class/struct/union
1>c:\users\steve\source\fmt\include\fmt\core.h(1073): error C2065: 'type_tag': undeclared identifier
1>c:\users\steve\source\fmt\include\fmt\core.h(1073): error C2131: expression did not evaluate to a constant
1>c:\users\steve\source\fmt\include\fmt\core.h(1073): note: a non-constant (sub-)expression was encountered
1>c:\users\steve\source\fmt\include\fmt\core.h(1197): error C2131: expression did not evaluate to a constant
1>c:\users\steve\source\fmt\include\fmt\core.h(1082): note: failure was caused by non-constant arguments or reference to a non-constant symbol
1>c:\users\steve\source\fmt\include\fmt\core.h(1082): note: see usage of 'value'

1 ответ

Решение

Чтобы отформатировать указатель, вы можете либо привести его к void*:

std::string s = fmt::format("{},{}", static_cast<void*>(pAccels), count);

или завернуть в fmt::ptr:

std::string s = fmt::format("{},{}", fmt::ptr(pAccels), count);

Рабочий пример для Godbolt: https://godbolt.org/z/sCNbjr

Обратите внимание, что format использует синтаксис строки формата, подобный Python, а не printfи возвращает std::string объект.

Другие вопросы по тегам