2017-03-16 89 views
3

我使用一个名为fmt的格式化库(http://fmtlib.net/latest/)。将initializer_list转换为variadic模板

其中一个可能的用途是:

fmt::format("Hello, {name}! The answer is {number}. Goodbye, {name}.", fmt::arg("name", "World"), fmt::arg("number", 42)); 

我想换一个函数调用这个,我会为拨打:

myFunction(myString, {"name", "World"}, {"number", 42}); 

任何数量的参数。

到现在为止,我只成功地做了功能callabel与对的列表:

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不能在函数之间传递。

+1

人们可以限定具有一个模板构造函数的一类,即,'模板 ARG(常量字符*名,T &&值)'和'{“号码”,42}'将然后使用统一的初始化语法成功地结合到类,并构造它。然而,我想不出一种方法来定义一个函数,该函数使用'arg'的可变参数列表。看起来像一个参数包不喜欢支撑统一初始化语法... –

+0

当你将它们传递给'fmt :: format'时,你的PS *不能为真。我期望它只能通过参考值得到它们 – Caleth

回答

0

尝试移动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)); 
0

不正是你问,因为你有打电话给你的功能

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_sequencestd::make_index_sequence(),所以从C++ 14开始编译;但是很容易为这个类创建一个替代品,并且这个函数也可以用于C++ 11。