2017-03-16 86 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。