程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++11 可變參數模板,可變模板

C++11 可變參數模板,可變模板

編輯:C++入門知識

C++11 可變參數模板,可變模板


在C++11之前, 有兩個典型的受制於模板功能不強而導致代碼重復難看的問題, 那就 function object 和 tuple。 拿 function objects 來說, 需要一個返回類型參數及N個參數類型參數。 但因為變長參數模板不受支持,導致不得不重復書寫7、8個模板類,但最終也只能支持7、8個參數的 function object。C++11中最終為我們帶來了強大的變長 參數模板功能,這些問題也隨之迎刃而解了。 

可變參數模板(Variadic Template)故名思義,即可以接受任意數量參數的類/函數模板。 其聲明方式為

template<typename... Args>
class VariadicTemplate;

當然non-type參數也是支持的比如 template<int... Args> class VariadicIntTemplate;

這裡Args代表0-N個類型參數,也就是說VariadicTemplate<>也是有效的模板實例。

C++11 翻新了省略號(...)操作符來支持對這種模板參數的訪問及使用。

類型展開

將所有模板參數展開在當前位置,用來調用其它模板、聲明函數指針類型

復制代碼
template<typename ...Args>
int foo() {
    int (*p)(Args...) = bar<Args...>;
    p(1, 0.5);
    return bar<Args...>(1, 0.5); 
}
復制代碼

對於 foo<int, float> 實例,其 p 的類型為 int (*)(int, float) 而 return 語句將調用 bar<int, float>(1, 0.5)

此外還可以展開類型參數用來指定基類列表

template<typename... Args>
class foo : Args...{
};

foo<bar, barz> f; // 該類繼承 bar, barz 兩個基類

Parameter Packs / Initialization Lists

通過省略號操作符可以聲明參數包,這些參數包可以在函數的參數位置展開。

template<typename ...Args>
void foo(Args... args) {
}

當使用 foo<int, float> 時,其有兩參數,一個整數,一個float,因此調用方法為 foo<int, float>(1, 0.1f);

此外還可以將參數包展開到構造函數的初始化列表

復制代碼
template<typename... Args>
class foo : Args...{
public:
    foo(Args...args):Args(args)...{
    }
};

foo<bar, barz> f(bar(), barz());
復制代碼

sizeof... operator

要獲取模板變長參數的實參長度,使用 sizeof... 運算符,它也可以被用於 Parameter Packs

復制代碼
template<typename ... Args>
size_t foo() {
    return sizeof...(Args);
}
template<typename ... Args>
size_t fooz(Args ...args) {
    return sizeof...(args);
}
復制代碼

以上就是變長參數的基本用法,但真正發揮作用,往往還要借助模板特化 (Template Specialization)

可變參數模板與模板特化

可變參數模板與普通模板一樣,可以進行特化,從而實現一些有意義的模式

復制代碼
template<typename ... Args>
void output(Args ... args) {
}
template<typename Arg0, typename ... Args>
void output(Arg0 arg0, Args ... args) {
    std::cout << arg0;
    output<Args...>(args...);
}
template<>
void output() {
}

/*------------------------------*/
typedef decltype(std::cout) cout_type;
auto endl = std::endl<cout_type::char_type, cout_type::traits_type>;
output(1, 0.3, (void*)nullptr, "string", 'c', endl);
復制代碼

以上代碼輸出

10.30stringc

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved