Re: [問題] 動態決定variadic 函數的參數個數
※ 引述《Wush978》之銘言:
: 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
: hiredis, C client of redis server
: 問題(Question):
: hiredis中提供了一個類似`printf`的API來傳送指令給redis server:
: ex:
: ```c
: reply = redisCommand(context, "SET foo %s", value);
: reply = redisCommand(context, "SET foo %s %s %s", value1, value2, value3);
: ```
: 我希望後面接的參數是可以動態決定數量的。因此我想要把它包成一個繼承自
: `std::ostream`的class
: 如此一來,要動態決定參數數量就變得很簡單:
: ```cpp
: Command << "SET foo " << value1 << value2 << value3;
: ```
: 但是目前函式庫只有提供:
: void *redisvCommand(redisContext *c, const char *format, va_list ap);
: void *redisCommand(redisContext *c, const char *format, ...);
: 不知道有沒有人有用C++處理variadic function的經驗。
: 有一種解法是自行寫出va_list的資料結構後直接餵給`redisvCommand`,
: 但是這種寫法似乎不容易跨平台,所以我先不考慮。
: 請問有沒有人有更好的作法?
其實這不算動態決定, 因為傳進去的引數個數都寫死在程式
碼裡了.
我們需要一個函式 format(), 它可以回傳 redisCommand()
需要的格式字串, 格式字串怎麼產生呢? 由參數的型態而定.
也就是說遇到下列定義時:
int value1;
double value2;
format(value1, value2); // 回傳 "%d %f"
1) 我們需要 template function 來得知引數型態
2) 我們需要函式接受任意個數引數.
C++11 的 feature: Variadic template 就能達成這件事
-> http://ppt.cc/LFuE
一開始的框架類似長這樣:
template <typename... Ts>
std::string format(Ts&&... values);
在 format() 內部我們必須將 Ts 展開並且對逐個型別取得
對應的 specifier. 首先針對每一個型別, 設計專用的
meta-function:
template <typename T>
struct get_specifier;
template <>
struct get_specifier<int> {
static constexpr char const* value = "%d";
};
...
為了能順利地迭代每個引數, 我會將它們包裝成 tuple, 有
現成工具要取得特定位置的型別也很簡單. 創建 format()
的 helper class 如下:
template <size_t Index, typename... Ts>
struct format_runner<Index, std::tuple<Ts...>> {
using tuple_type = std::tuple<Ts...>;
template <typename String>
static String execute(String&& init) {
return format_runner<
Index-1,
tuple_type
>::execute(std::forward<String>(init))
+ " "
+ get_specifier<
typename std::tuple_element<
Index,
tuple_type
>::type
>::value;
}
};
用遞迴的方式展開, 記得寫一個 format_runner<0, ...> 來
終止具現化. 能傳型態就傳型態, 或用 std::forward() 以免
拖垮效能.
最後的實作長得像這樣:
http://ideone.com/dLjgZY
當然 get_specifier<T> 你還可以再設計得好一點
--
≡≡≡≡╔═══╗╔═══╗ ◎ ╔═╗═╗╔═══╗╔═══╗╔╦═╦╗≡≡≡≡
≡金栽經║ ╔╗ ║║ ╔╗ ║╔╗║ ║ ║║ ═ ║║ ╔╗ ║║║ ║║RAINNOUS
≡≡≡≡║ ╚╝ ║║ ╚╝ ║║║║ ║║ ╞╣║ ║║ ║║ ║≡≡≡≡
≡≡≡≡║ ═╣║ ╥ ║║║║ ║ ║║ ═ ║║ ╚╝ ║║ ║ ║≡≡≡≡
≡高佑麗╚═╩═╝╚═╩═╝╚╝╚═╚═╝╚═══╝╚═══╝╚═╩═╝鄭允慧≡
≡≡≡≡≡趙賢榮≡≡≡金智淑≡≡≡RAINBOW≡≡≡盧 乙≡≡≡吳勝雅≡ψmocki
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 112.105.158.161
※ 編輯: loveme00835 來自: 112.105.158.161 (07/24 23:44)
※ 編輯: loveme00835 來自: 223.138.193.188 (07/25 09:15)
→
07/25 10:27, , 1F
07/25 10:27, 1F
推
07/25 16:45, , 2F
07/25 16:45, 2F
→
07/25 22:20, , 3F
07/25 22:20, 3F
推
07/25 23:32, , 4F
07/25 23:32, 4F
→
07/25 23:32, , 5F
07/25 23:32, 5F
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 2 篇):