2018年11月14日 星期三

c++ 實作輸入不定數量參數(variadic parameter)的方法(method)

c 語言用一些巨集 va_list, va_start,  va_arg, va_end 去實現不定數量參數的函式功能,  參數不定量使用省略符號 ... (連續3個句點)來表示, 同時必須明示或暗示後續輸入參數的數量, 像是常用 printf  就可以透過第一個字串參數去得知後續還有多少參數需要擷取利用. 實際上編譯器(compiler)可以得知輸入參數的數量, 只是不易操作, 對程式設計師而言, 不定數量參數有其方便使用的地方, c++ 利用 parameter pack 像是 sizeof...( ) 運算元計算得知輸入有多少數量的參數,  利用 sizeof...( ) 並將函式包裝起來, 可以實現一個不需參數數量的函式, 同時理解樣版函式(template function)的運作方式:
// variadic.c
#include <stdio.h>
#include <stdarg.h>
void __expricitFunction(size_t argc, ...) {// 明示後續還有 argc 個數量的參數
    va_list args;
    va_start(args, argc);
    for (int i = 0; i < argc; i++)    printf("%d\n", va_arg(args, int) );  // 用整數解釋輸入參數   
    va_end(args);
}
template <typename... List> // 使用逗號分開列表,  通用的型態名稱使用 List 當佔位符
void  variadicParameter(List... parameter){// 這是樣版函式, 由 compiler 決定函式型態
    __expricitFunction(sizeof...(parameter), parameter...);// 呼叫真正的函式
}
int main( ) {
     variadicParameter(1, 2, 3); // 呼叫樣版函式
     variadicParameter(4, 5, 6, 7, 8); // 呼叫另一種樣版函式
     variadicParameter('a', 'b', 'c', 'd', 'e'); // 呼叫另一種樣版函式
}
上述  typename... List 通常稱為 template parameter pack(一串型態表列, 有些人將通用型態取名為 Args, Rest ...等等都是隨性而取名), 作用是呼叫樣版函式時才指定表列型態(type), 名稱只是一個佔位符號(place holder), 而後續的 List... parameter 則稱為 parameter pack  (型態是 List 的表列參數), 用 g++ 編譯並執行:
      g++  variadic.c && ./a.out
這是輸出結果:
1
2
3
4
5
6
7
8
97
98
99
100
101


沒有留言: