i使用名为fmt(http://fmtlib.net/latest/)的格式库。
可能的用途之一是:
fmt::format("Hello, {name}! The answer is {number}. Goodbye, {name}.", fmt::arg("name", "World"), fmt::arg("number", 42));
我想将此调用包装在我称为:
的函数中myFunction(myString, {"name", "World"}, {"number", 42});
对于任何参数的数量。
到目前为止,我只成功地使用对列表进行函数可召唤:
myFunction(myString, std::make_pair("name", "World"), std::make_pair("number", 42));
使用功能:
std::string myFunction(const char* str, const Args&... rest) const
{
return fmt::format(mLocale.getPOILabel(label), fmt::arg(rest.first, rest.second)...);
}
但是我不想使用对。
我该怎么办?
ps:fmt::arg
不能在功能之间传递。
不是您问什么,因为您必须称自己的功能为
myFunction(myString, "name", "World", "number", 42);
而不是
myFunction(myString, {"name", "World"}, {"number", 42});
,但以下是一个例子(对不起,但是baz()
未经测试)
#include <tuple>
#include <string>
#include <utility>
#include <iostream>
// fmt headers
template <typename ... Ps>
std::string baz (char const * frmt,
std::pair<char const *, Ps> const & ... ps)
{ return fmt::format(frmt, fmt::arg(ps.first, ps.second)...); }
template <typename ... Ts, std::size_t ... Is>
std::string bar (char const * frmt, std::tuple<Ts...> const & t,
std::index_sequence<Is...> const &)
{ return baz(frmt, std::get<Is>(t)...); }
template <typename ... Ts>
std::string foo (char const * frmt, std::tuple<Ts...> const & t)
{ return bar(frmt, t, std::make_index_sequence<sizeof...(Ts)>{}); }
template <typename ... Ts, typename P1, typename P2, typename ... Args>
std::string foo (char const * frmt, std::tuple<Ts...> const & t,
P1 const & p1, P2 const & p2, Args const & ... args)
{ return foo(frmt,
std::tuple_cat(t, std::make_tuple(std::make_pair(p1, p2))), args...); }
template <typename ... Args>
std::string myFunction (char const * frmt, Args const & ... args)
{ return foo(frmt, std::tuple<>{}, args...); }
int main()
{
myFunction("format", "name", "World", "number", 42);
}
观察此示例使用std::index_sequence
和std::make_index_sequence()
,因此从C 14开始编译;但是,很容易创建此类的替代品,并且此功能也可以与C 11一起使用。
尝试移动fmt :: arg的结果,而不是复制或传递const引用。
template<typename ... Args>
std::string myFunction(const char* str, Args&&... rest) const
{
return fmt::format(mLocale.getPOILabel(label), std::forward<Args...>(rest)...);
}
myFunction(myString, fmt::arg("name", "World"), fmt::arg("number", 42));