迭代引數包
通常,我們需要對可變引數模板引數包中的每個元素執行操作。有很多方法可以做到這一點,並且使用 C++ 17 可以更輕鬆地讀取和寫入解決方案。假設我們只想列印包中的每個元素。最簡單的解決方案是遞迴:
Version >= C++ 11
void print_all(std::ostream& os) {
// base case
}
template <class T, class... Ts>
void print_all(std::ostream& os, T const& first, Ts const&... rest) {
os << first;
print_all(os, rest...);
}
我們可以使用擴充套件器技巧,在單個函式中執行所有流式傳輸。這樣做的優點是不需要第二次過載,但缺點是可靠性低於恆星:
Version >= C++ 11
template <class... Ts>
void print_all(std::ostream& os, Ts const&... args) {
using expander = int[];
(void)expander{0,
(void(os << args), 0)...
};
}
有關其工作原理的說明,請參閱 TC 的優秀答案 。
Version >= C++ 17
使用 C++ 17,我們在我們的工具庫中獲得了兩個強大的新工具來解決這個問題。第一個是 fold-expression:
template <class... Ts>
void print_all(std::ostream& os, Ts const&... args) {
((os << args), ...);
}
第二個是 if constexpr
,它允許我們在一個函式中編寫我們的原始遞迴解決方案:
template <class T, class... Ts>
void print_all(std::ostream& os, T const& first, Ts const&... rest) {
os << first;
if constexpr (sizeof...(rest) > 0) {
// this line will only be instantiated if there are further
// arguments. if rest... is empty, there will be no call to
// print_all(os).
print_all(os, rest...);
}
}