ãã©ã¡ã¼ã¿ããã¯(C++11以ä¸)
ãã³ãã¬ã¼ããã©ã¡ã¼ã¿ããã¯ã¯ãä»»æåã®ãã³ãã¬ã¼ã弿° (éåãåãã¾ãã¯ãã³ãã¬ã¼ã) ãåçãããã³ãã¬ã¼ã弿°ã§ãã 颿°ãã©ã¡ã¼ã¿ããã¯ã¯ãä»»æåã®é¢æ°å¼æ°ãåçãã颿°å¼æ°ã§ãã
å°ãªãã¨ã1ã¤ã®ãã©ã¡ã¼ã¿ããã¯ãæã¤ãã³ãã¬ã¼ãã¯å¯å¤é·å¼æ°ãã³ãã¬ã¼ãã¨è¨ãã¾ãã
[ç·¨é] æ§æ
ãã³ãã¬ã¼ããã©ã¡ã¼ã¿ãã㯠(ã¨ã¤ãªã¢ã¹ãã³ãã¬ã¼ããã¯ã©ã¹ãã³ãã¬ã¼ãã夿°ãã³ãã¬ã¼ãããã³é¢æ°ãã³ãã¬ã¼ãã®ãã³ãã¬ã¼ã弿°ãªã¹ãã§ä½¿ç¨ã§ãã¾ã):
type ... Args(ãªãã·ã§ã³)
|
(1) | ||||||||
typename|class ... Args(ãªãã·ã§ã³)
|
(2) | ||||||||
template < parameter-list > typename(C++17)|class ... Args(ãªãã·ã§ã³)
|
(3) | ||||||||
颿°ãã©ã¡ã¼ã¿ãã㯠(宣è¨åã®å½¢å¼ã®ã²ã¨ã¤) (å¯å¤é·å¼æ°é¢æ°ãã³ãã¬ã¼ãã®é¢æ°å¼æ°ãªã¹ãã§ä½¿ç¨ã§ãã¾ã):
Args ... args(ãªãã·ã§ã³)
|
(4) | ||||||||
ãã©ã¡ã¼ã¿ããã¯ã®å±é (å¯å¤é·å¼æ°ãã³ãã¬ã¼ãã®æ¬ä½ã§ä½¿ç¨ã§ãã¾ã):
pattern ...
|
(5) | ||||||||
pattern
ã®ã³ã³ãåºåãã®ãªã¹ãã«å±éããã¾ãã ãã¿ã¼ã³ã«ã¯å°ãªãã¨ã1ã¤ã®ãã©ã¡ã¼ã¿ããã¯ãå«ã¾ãã¦ããªããã°ãªãã¾ããã[ç·¨é] 説æ
å¯å¤é·å¼æ°ã¯ã©ã¹ãã³ãã¬ã¼ãã¯ãä»»æåã®ãã³ãã¬ã¼ã弿°ãç¨ãã¦å®ä½åã§ãã¾ãã
template<class ... Types> struct Tuple {}; Tuple<> t0; // OKã Types ã¯å¼æ°ãæã¡ã¾ããã Tuple<int> t1; // OKã Types ã¯1åã®å¼æ° (int) ãæã¡ã¾ãã Tuple<int, float> t2; // OKã Types ã¯2åã®å¼æ° (int, float) ãæã¡ã¾ãã Tuple<0> error; // ã¨ã©ã¼ã 0 ã¯åã§ã¯ããã¾ããã
å¯å¤é·å¼æ°é¢æ°ãã³ãã¬ã¼ãã¯ãä»»æåã®é¢æ°å¼æ°ãç¨ãã¦å¼ã¶ãã¨ãã§ãã¾ãã ãã³ãã¬ã¼ã弿°ã¯ãã³ãã¬ã¼ãã®å®å¼æ°æ¨å®ã«ãã£ã¦æ¨å®ããã¾ãã
template<class ... Types> void f(Types ... args); f(); // OKã Types ã¯å¼æ°ãæã¡ã¾ããã f(1); // OKã Types ã¯1åã®å¼æ° (int) ãæã¡ã¾ãã f(2, 1.0); // OKã Types ã¯2åã®å¼æ° (int, double) ãæã¡ã¾ãã
ãã©ã¤ããªã¯ã©ã¹ãã³ãã¬ã¼ãã§ã¯ããã³ãã¬ã¼ããã©ã¡ã¼ã¿ããã¯ã¯ããã³ãã¬ã¼ã仮弿°ãªã¹ãã®æå¾ã®å¼æ°ã§ãªããã°ãªãã¾ããã 颿°ãã³ãã¬ã¼ãã§ã¯ããã³ãã¬ã¼ããã©ã¡ã¼ã¿ããã¯ã¯ããã®å¾ã®å¼æ°ãã¹ã¦ãå®å¼æ°ããæ¨å®ã§ãããããã©ã«ã弿°ãæã¤ãªãã°ãæå¾ã§ãªãã¦ãæ§ãã¾ããã
template<typename... Ts, typename U> struct Invalid; // ã¨ã©ã¼ã Ts ã¯æå¾ã§ãªããã°ãªãã¾ããã template<typename ...Ts, typename U, typename=void> void valid(U, Ts...); // OKã U ã¯æ¨å®ã§ãã¾ãã // void valid(Ts..., U); // ãã®å ´åã¯ã¨ã©ã¼ã§ãã Ts... ã¯ãã®ä½ç½®ã§ã¯éæ¨å®æèã§ãã valid(1.0, 1, 2, 3); // OKã U 㯠double ã¨æ¨å®ããã Ts 㯠{int,int,int} ã¨æ¨å®ããã¾ãã
[ç·¨é] ããã¯å±é
ãã¿ã¼ã³ (å°ãªãã¨ã1ã¤ã®ãã©ã¡ã¼ã¿ããã¯ã®ååãå«ã¾ãã¦ããªããã°ãªãã¾ãã) ã«çç¥è¨å·ãç¶ãããã®ã¯ããã®ãã¿ã¼ã³ã®0å以ä¸ã®ã³ã³ãåºåãã®å®ä½åã«å±éããã¾ãã ãã©ã¡ã¼ã¿ããã¯ã®ååã¯ããã¯å ã®åè¦ç´ ã«é çªéãã«ç½®ãæãããã¾ãã
template<class ...Us> void f(Us... pargs) {} template<class ...Ts> void g(Ts... args) { f(&args...); // ã&args...ããããã¯å±éã§ãã // ã&argsãããã¿ã¼ã³ã§ãã g(1, 0.2, "a"); // Ts... args 㯠int E1, double E2, const char* E3 ã«å±éããã // &args... 㯠&E1, &E2, &E3 ã«å±éããã // Us... pargs 㯠int* E1, double* E2, const char** E3 ã«å±éããã¾ãã
1ã¤ã®ãã¿ã¼ã³å ã«è¤æ°ã®ãã©ã¡ã¼ã¿ããã¯ã®ååãç¾ããå ´åã¯ããããã¯åæã«å±éããã¾ã (åãé·ãã§ãªããã°ãªãã¾ãã)ã
template<typename...> struct Tuple {}; template<typename T1, typename T2> struct Pair {}; template<class ...Args1> struct zip { template<class ...Args2> struct with { typedef Tuple<Pair<Args1, Args2>...> type; // ãPair<Args1, Args2>...ããããã¯å±éã§ãã // ãPair<Args1, Args2>ãããã¿ã¼ã³ã§ãã }; }; typedef zip<short, int>::with<unsigned short, unsigned>::type T1; // Pair<Args1, Args2>... 㯠// Pair<short, unsigned short>, Pair<int, unsigned int> ã«å±éããã¾ãã // T1 㯠Tuple<Pair<short, unsigned short>, Pair<int, unsigned>> ã§ãã typedef zip<short>::with<unsigned short, unsigned>::type T2; // ã¨ã©ã¼ãããã¯å±éã«é·ãã®ç°ãªããã©ã¡ã¼ã¿ããã¯ãå«ã¾ãã¾ãã
ããã¯å±éãå¥ã®ããã¯å±éå ã«ãã¹ããã¦ããå ´åã¯ãå å´ã®ããã¯å±éå ã«ç¾ãããã©ã¡ã¼ã¿ããã¯ã¯å å´ã®ããã¯å±éã«ãã£ã¦å±éããããããå¤å´ã®ããã¯å±éå ã ããã©ãå å´ã®ããã¯å±éå ã§ã¯ãªãå¥ã®ããã¯å±éãåå¨ããªããã°ãªãã¾ããã
template<class ...Args> void g(Args... args) { f(const_cast<const Args*>(&args)...); // ãconst_cast<const Args*>(&args)ãããã¿ã¼ã³ã§ãã // 2ã¤ã®ãã㯠(Args 㨠args) ãåæã«å±éããã¾ãã f(h(args...) + args...); // ãã¹ãããããã¯å±éã // å å´ã®ããã¯å±é㯠args... ã§ãã ã¾ããããä¾ãã° E1, E2, E3 ã®ããã«å±éããã¾ãã // å¤å´ã®ããã¯å±é㯠h(E1, E2, E3) + args... ã§ãã æ¬¡ã«ãããä¾ãã° // h(E1,E2,E3) + E1, h(E1,E2,E3) + E2, h(E1,E2,E3) + E3 ã®ããã«å±éããã¾ãã }
[ç·¨é] å±éã®å ´æ
å±éãè¡ãããå ´æã«ãã£ã¦ãçµæã®ã³ã³ãåºåãã®ãªã¹ãã¯ç°ãªã種é¡ã®ãªã¹ãã«ãªãã¾ã (颿°ã®å¼æ°ãªã¹ããã¡ã³ãåæååãªã¹ãã屿§ãªã¹ããªã©)ã 以ä¸ã¯ä½¿ç¨ã§ãããã¹ã¦ã®æèã®ä¸è¦§ã§ãã
[ç·¨é] 颿°ã®å®å¼æ°ãªã¹ã
颿°å¼ã³åºãæ¼ç®åã®æ¬å¼§å ã§ãããã¯å±éã使ç¨ã§ãã¾ãã ãã®å ´åãçç¥è¨å·ã®å·¦ã®æã大ããªå¼ã¾ãã¯æ³¢æ¬å¼§åæååãªã¹ããå±éããããã¿ã¼ã³ã«ãªãã¾ãã
f(&args...); // f(&E1, &E2, &E3) ã«å±éããã¾ãã f(n, ++args...); // f(n, ++E1, ++E2, ++E3) ã«å±éããã¾ãã f(++args..., n); // f(++E1, ++E2, ++E3, n) ã«å±éããã¾ãã f(const_cast<const Args*>(&args)...); // f(const_cast<const T1*>(&E1), const_cast<const T2*>(&E2), const_cast<const T3*>(&E3)) ã«å±éããã¾ãã f(h(args...) + args...); // f(h(E1,E2,E3) + E1, h(E1,E2,E3) + E2, h(E1,E2,E3) + E3) ã«å±éããã¾ãã
å½¢å¼çã«ã¯ã颿°å¼ã³åºãå¼ã®å¼ãªã¹ãã¯åæååãªã¹ãã«åé¡ããããã¿ã¼ã³ã¯åæååç¯ (ä»£å ¥å¼ã¾ãã¯æ³¢æ¬å¼§åæååãªã¹ãã®ãããã) ã§ãã
[ç·¨é] 丸æ¬å¼§åæåå
ç´æ¥åæåã颿°ã¹ã¿ã¤ã«ã®ãã£ã¹ããããã³ãã®ä»ã®æè (ã¡ã³ãåæååã new å¼ããªã©) ã®ä¸¸æ¬å¼§å ã§ãããã¯å±éã使ç¨ã§ãã¾ãã ãã®å ´åã®ã«ã¼ã«ã¯åç¯ã®é¢æ°å¼ã³åºãå¼ã«å¯¾ããã«ã¼ã«ã¨åä¸ã§ãã
Class c1(&args...); // Class::Class(&E1, &E2, &E3) ãå¼ã³ã¾ãã Class c2 = Class(n, ++args...); // Class::Class(n, ++E1, ++E2, ++E3) ãå¼ã³ã¾ãã ::new((void *)p) U(std::forward<Args>(args)...) // std::allocator::allocate
[ç·¨é] æ³¢æ¬å¼§åæåå
æ³¢æ¬å¼§åæååãªã¹ã (ãªã¹ãåæåããã®ä»ã®ããã¤ãã®æèã§ä½¿ç¨ããããåæååããã³å¥ã®æ³¢æ¬å¼§åæååãªã¹ãã®ãªã¹ããæ³¢æ¬å¼§ã§å²ã£ããã®) ã§ãåæ§ã«ãããã¯å±éã使ç¨ã§ãã¾ãã
template<typename... Ts> void func(Ts... args){ const int size = sizeof...(args) + 2; int res[size] = {1,args...,2}; // åæååãªã¹ãã¯è©ä¾¡é åºãä¿è¨¼ããããã // ããã¯ã®åè¦ç´ ã«å¯¾ãã¦é çªã«é¢æ°ãå¼ã¶ããã«ä½¿ç¨ã§ãã¾ãã int dummy[sizeof...(Ts)] = { (std::cout << args, 0)... }; }
[ç·¨é] ãã³ãã¬ã¼ãã®å®å¼æ°ãªã¹ã
ãã³ãã¬ã¼ãã®å®å¼æ°ãªã¹ãå ã®ä»»æã®ä½ç½®ã§ããã¯å±éã使ç¨ã§ãã¾ã (ãã®ãã³ãã¬ã¼ãããã®å±éã«ããããã弿°ãåããªãã°)ã
template<class A, class B, class...C> void func(A arg1, B arg2, C...arg3) { container<A,B,C...> t1; // container<A,B,E1,E2,E3> ã«å±éããã¾ãã container<C...,A,B> t2; // container<E1,E2,E3,A,B> ã«å±éããã¾ãã container<A,C...,B> t3; // container<A,E1,E2,E3,B> ã«å±éããã¾ãã }
[ç·¨é] 颿°ã®ä»®å¼æ°ãªã¹ã
颿°ã®ä»®å¼æ°ãªã¹ãã§ã弿°å®£è¨å
ã«çç¥è¨å·ãç¾ãã (Args ...
args ã®ããã«é¢æ°ãã©ã¡ã¼ã¿ããã¯ã表ãããããã§ãªããã«é¢ä¿ãªã) å ´åã¯ããã®å¼æ°å®£è¨ã¯ãã¿ã¼ã³ã§ãã
template<typename ...Ts> void f(Ts...) {} f('a', 1); // Ts... 㯠char, int ã«å±éããã¾ãã f(0.1); // Ts... 㯠double ã«å±éããã¾ãã template<typename ...Ts, int... N> void g(Ts (&...arr)[N]) {} int n[1]; g<const char, int>("a", n); // Ts (&...arr)[N] 㯠// const char (&)[2], int (&)[1] ã«å±éããã¾ãã
ãã¼ã: ãã¿ã¼ã³ Ts (&...arr)[N]
ã®å ´åãçç¥è¨å·ã¯æãå
å´ã®è¦ç´ ã§ã (ä»ã®ããã¯å±éã®ããã«æå¾ã®è¦ç´ ã§ã¯ããã¾ãã)ã
ãã¼ã: C++11 ã®ææ³ä¸ãæ¬å¼§ã§å²ã¾ããçç¥è¨å·ã¯ååãæã¤å¿
è¦ãããããã Ts (&...)[N]
ã¯ä½¿ç¨ã§ãã¾ãã (CWG #1488)ã
[ç·¨é] ãã³ãã¬ã¼ãã®ä»®å¼æ°ãªã¹ã
ãã³ãã¬ã¼ãã®ä»®å¼æ°ãªã¹ãã§ããã¯å±éã使ç¨ã§ãã¾ãã
template<typename... T> struct value_holder { template<T... Values> // éåãã³ãã¬ã¼ã仮弿°ãªã¹ãã«å±éããã¾ã struct apply { }; // (ä¾ãã° <int, char, int(&)[5]>)ã };
[ç·¨é] åºåºæå®åããã³ã¡ã³ãåæååãªã¹ã
ã¯ã©ã¹å®£è¨ã®åºåºã¯ã©ã¹ãªã¹ãã§ããã¯å±éã使ç¨ã§ãã¾ãã ä¸è¬çã«ã¯ããããã®åºåºã®ã³ã³ã¹ãã©ã¯ã¿ãå¼ã¶ããã«ãã¡ã³ãåæååãªã¹ãã§ãããã¯å±éã使ç¨ããå¿ è¦ãããã¾ãã
template<class... Mixins> class X : public Mixins... { public: X(const Mixins&... mixins) : Mixins(mixins)... { } };
[ç·¨é] ã©ã ããã£ããã£
ã©ã ãå¼ã®ãã£ããã£ç¯ã§ããã¯å±éã使ç¨ã§ãã¾ãã
template<class ...Args> void f(Args... args) { auto lm = [&, args...] { return g(args...); }; lm(); }
[ç·¨é] sizeof... æ¼ç®å
sizeof... æ¼ç®åãåæ§ã«ããã¯å±éã«åé¡ããã¾ãã
template<class... Types> struct count { static const std::size_t value = sizeof...(Types); };
åçä¾å¤æå®åçä¾å¤æå®ã®ä¾å¤ãªã¹ãã§ãããã¯å±éã使ç¨ã§ãã¾ãã template<class...X> void func(int arg) throw(X...) { // ... ç¶æ³ã«å¿ãã¦ç°ãªã X ãæãã ... } |
(C++17æªæº) |
[ç·¨é] ã¢ã©ã¤ã¡ã³ãæå®å
ãã¼ã¯ã¼ã alignas ã§ä½¿ç¨ãããåã®ãªã¹ãããã³å¼ã®ãªã¹ãã®ä¸¡æ¹ã§ããã¯å±éã使ç¨ã§ãã¾ãã
[ç·¨é] 屿§ãªã¹ã
屿§ã®ãªã¹ãã§ [[attributes...]] ã®ããã«ããã¯å±éã使ç¨ã§ãã¾ãã ä¾: void [[attributes...]] function()
ç³ã¿è¾¼ã¿å¼ç³ã¿è¾¼ã¿å¼ã§ã¯ããã¿ã¼ã³ã¯æªå±éã®ãã©ã¡ã¼ã¿ããã¯ãå«ã¾ãªãé¨åå¼å ¨ä½ã§ãã using 宣è¨using 宣è¨ã§ã¯ã宣è¨åã®ãªã¹ãã«çç¥è¨å·ãç¾ãã¦ãæ§ãã¾ããã ããã¯ãã©ã¡ã¼ã¿ããã¯ããæ´¾çããã¨ãã«ä¾¿å©ã§ãã template <typename... bases> struct X : bases... { using bases::g...; }; X<B, D> x; // OKã B::g 㨠D::g ã両æ¹ã¨ãå°å ¥ããã¾ãã |
(C++17以ä¸) |
[ç·¨é] ãã¼ã
This section is incomplete Reason: a few words about partial specializations and other ways to access individual elements? Mention recursion vs logarithmic vs shortcuts such as fold expressions |
[ç·¨é] ä¾
#include <iostream> void tprintf(const char* format) // åºæ¬ã®é¢æ° { std::cout << format; } template<typename T, typename... Targs> void tprintf(const char* format, T value, Targs... Fargs) // å¯å¤é·å¼æ°ãæã¤å帰çãªé¢æ° { for ( ; *format != '\0'; format++ ) { if ( *format == '%' ) { std::cout << value; tprintf(format+1, Fargs...); // å帰å¼ã³åºã return; } std::cout << *format; } } int main() { tprintf("% world% %\n","Hello",'!',123); return 0; }
åºå:
Hello world! 123
ä¸è¨ã®ä¾ã¯ std::printf ã«ä¼¼ã颿°ãå®ç¾©ãã¾ãã æ¸å¼æååå ã®æå % ã®ååºç¾ãå¤ã«ç½®ãæãã¾ãã
1ã¤ãã®ãªã¼ãã¼ãã¼ãã¯æ¸å¼æååã ããæ¸¡ãã弿°å±éããªãã¨ãã«å¼ã°ãã¾ãã
2ã¤ãã®ãªã¼ãã¼ãã¼ãã¯æåã®å¼æ°ã®ããã«åé¢ããããã³ãã¬ã¼ã弿°ã¨ãã©ã¡ã¼ã¿ããã¯ãåãã¾ãã ããã«ãã空ã«ãªãã¾ã§æ®ãã®å¼æ°ã渡ãã¦å帰å¼ã³åºããããã¨ãå¯è½ã«ãªãã¾ãã
Targs
ã¯ãã³ãã¬ã¼ããã©ã¡ã¼ã¿ããã¯ã§ã Fargs
ã¯é¢æ°ãã©ã¡ã¼ã¿ããã¯ã§ãã
[ç·¨é] é¢é£é ç®
颿°ãã³ãã¬ã¼ã | |
ã¯ã©ã¹ãã³ãã¬ã¼ã | |
sizeof... | ãã©ã¡ã¼ã¿ããã¯å ã®è¦ç´ æ°ãåãåããã¾ã |
C ã¹ã¿ã¤ã«ã®å¯å¤é·å¼æ°é¢æ° | |
ããªããã»ããµãã¯ã | ãå¯å¤é·å¼æ°ãåãã¾ã |
ç³ã¿è¾¼ã¿å¼ |