談的是 templateios
變化的是 template parameterless
參數個數(variable number)ide
function template
完成參數類型(different type)函數
class template
完成。void func() { /* ... */ } template <typename T, typename ... Types> void func(const T & firstArg, const Types &...args) { // 處理 firstArg func(args...); }
since C++11, template can have parameters that accepta variable number of template arguments
. This ability is called variadic template. For example, you can use the following to call printX() fora aviable number of argument of diferent types
.
(從C ++ 11開始,模板能夠具備接受可變數量的模板參數的參數。 此功能稱爲可變參數模板。 例如,你能夠使用如下代碼爲不一樣類型的大量參數調用printX()。)佈局
文件:Test.cppthis
#include <iostream> #include <bitset> using namespace std; void printX() { } template <typename T, typename ...Type> void printX(const T &firstArg, const Type &...args) { cout << sizeof...(args) << " "<< firstArg << endl; printX(args...); } int main() { printX(7.5, "hello", bitset<16>(377), 42); return 0; }
輸出:spa
3 7.5 2 hello 1 0000000101111001 0 42
If one or more arguments are passed, the function template is used, which byspecifying the first argument separately
allows the first argument to print and thenrecursively
calls printX() for the remaining argument.To end the recursion, the non-template overload of printX() is provided
.
(若是傳遞了一個或多個參數,則使用函數模板,經過分別指定第一個參數,能夠打印第一個參數,而後遞歸地爲其他參數調用printX()。爲告終束遞歸,提供了printX()的非模板重載。)code
使用 variadic template 重寫 printf()orm
文件:Test.cpp對象
#include <iostream> namespace T { void printf(const char *s) { while (*s) { if ((*s == '%') && (*(++s) != '%')) throw std::runtime_error("invalid format string: missing argument"); std::cout << *s++; } } template <typename T, typename ...Args> void printf(const char *s, T value, Args ...args) { while (*s) { if ((*s == '%') && (*(++s) != '%')) { std::cout << value; printf(++s, args...); return; } std::cout << *s++; } throw std::logic_error("extra argument provided to printf"); } } int main() { int *pi = new int{}; T::printf("%d %s %p %f\n", 15, "This is Ace", pi, 3.1415926); delete pi; return 0; }
文件:Test.cpp
#include <iostream> using namespace std; struct _Iter_less_iter { template<typename _Iterator1, typename _Iterator2> bool operator() (_Iterator1 __it1, _Iterator2 __it2) const { return *__it1 < *__it2; } }; inline _Iter_less_iter __iter_less_iter() { return _Iter_less_iter(); // 臨時對象 } template <typename _ForwardIterator, typename _Compare> _ForwardIterator __max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { if (__first == __last) return __first; _ForwardIterator __result = __first; while (++__first != __last) if (__comp(__result, __first)) __result = __first; return __result; } template <typename _ForwardIterator> inline _ForwardIterator max_element(_ForwardIterator __first, _ForwardIterator __last) { return __max_element(__first, __last, __iter_less_iter()); } template <typename _Tp> inline _Tp max(initializer_list<_Tp> __l) { return *max_element(__l.begin(), __l.end()); } int main() { cout << max({57, 48, 60, 100, 20, 18}) << endl; return 0; }
若參數類型都相同,則無需使用 variadic templates, 使用 initializer_list<T> 足夠。
#include <iostream> using namespace std; namespace T { template <typename T> T max(T value) { return value; } template <typename T> T max(T lh, T rh) { return lh > rh ? lh : rh; } template <typename T, typename ...Args> T max(T value, Args ...args) { return max(value, max(args...)); } } int main() { cout << T::max(57, 48, 60, 100, 20, 18) << endl; return 0; }
文件:Test.cpp
#include <iostream> #include <tuple> #include <string> #include <bitset> using namespace std; template <int IDX, int MAX, typename ...Args> struct PRINT_TUPLE { static void print(std::ostream &os, const tuple<Args...> &t) { os << get<IDX>(t) << (IDX+1==MAX ? "" : ","); PRINT_TUPLE<IDX+1, MAX, Args...>::print(os, t); } }; // 特化實現,遞歸出口 template <int MAX, typename ...Args> struct PRINT_TUPLE <MAX, MAX, Args...> { static void print(ostream &os, const tuple<Args...> &t) { } }; //-------- template <typename ...Args> ostream &operator << (ostream &os, const tuple<Args...> &t) { cout << "["; PRINT_TUPLE<0, sizeof...(Args), Args...>::print(os, t); cout << "]"; return os; } int main() { cout << make_tuple(7.5, string("hello"), bitset<16>(377), 42) << endl; return 0; }
輸出:
[7.5,hello,0000000101111001,42]
文件:Test.cpp
#include <iostream> #include <string> using namespace std; namespace T { // 泛型 template <typename ...Value> class tuple; // 特化出口 template <> class tuple <> { }; // 特化 template <typename Head, typename ...Tail> class tuple<Head, Tail...> : private tuple<Tail...> // 私有繼承,代表兩類之間不是 ‘isa’ ,僅是內存繼承關機 { typedef tuple<Tail...> inherited; // using inherited=tuple<Tail...>; public: tuple() { } tuple(Head v, Tail... vtail) : inherited(vtail...), m_head(v) { } Head head() { return m_head; } inherited& tail() { return *this; } protected: Head m_head; }; } int main() { T::tuple<int, float, string> t(41, 6.3f, "nico"); cout << t.head() << endl; cout << t.tail().head() << endl; cout << t.tail().tail().head() << endl; return 0; }
輸出:
41 6.3 nico
文件:Test.cpp
#include <iostream> #include <string> using namespace std; namespace T { // 泛化 template <typename ...Value> class tuple; // 特化出口 template <> class tuple <> { }; // 特化 template <typename Head, typename ...Tail> class tuple <Head, Tail...> { typedef tuple<Tail...> composited; // using composited = tuple<Tail...>; public: tuple() { } tuple(Head v, Tail... vtail) : m_tail(vtail...), m_head(v) { } Head head() { return m_head; } composited& tail() { return m_tail; } protected: composited m_tail; Head m_head; }; } int main() { T::tuple<int, float, string> t(41, 6.3f, "nico"); cout << t.head() << endl; cout << t.tail().head() << endl; cout << t.tail().tail().head() << endl; return 0; }
輸出:
41 6.3 nico