如何使用fmt库格式化指针?

时间:2019-05-10 00:03:19

标签: c++ templates compiler-errors formatting fmt

我正在采纳一些伙计的建议,并调查fmt库: http://fmtlib.net

它似乎具有我需要的功能,并声称支持%p(指针),但是在编译使用%p的代码时,出现了一长串模板错误(无法理解)。我将在此结尾发布它们。

如果我拉出%p和相应的指针参数,那么它将在VS2017 c ++ 17上编译。

但是,我不知道如何解码模板错误,或者对为什么它首先不接受%p参数有一定的了解。

我尝试将参数强制转换为(void*)-同样的问题。
我尝试在格式化程序{}中使用python样式语法-相同的问题。
我已经将%p位与其他格式分开了-同样的问题。

我看到了对用户类型的支持-但在这种情况下,我只想将其输出为原始指针值。我可以跳过它,毕竟指针地址真的有多有价值?但是,当然,这意味着在从sprintffmt::format的转换过程中,需要进行更多工作以查找所有%p并“与他们一起做某事”,例如淘汰它们。

但是文档似乎表明支持%p-http://fmtlib.net/latest/syntax.html(大约下降3/4-搜索“ pointer”或“ 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 个答案:

答案 0 :(得分: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对象。