CppTemplateTutorial.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. #include "stdafx.h"
  2. #include <vector>
  3. #define WRONG_CODE_ENABLED 0
  4. // 0. Basic Form
  5. namespace _0
  6. {
  7. template <typename T> // Old fasion: template <class T>
  8. class ClassA
  9. {
  10. T a;
  11. T* b;
  12. T foo();
  13. void foo2(T const&);
  14. };
  15. template <int Sz>
  16. class ClassB
  17. {
  18. int arr[Sz];
  19. };
  20. size_t a = sizeof(ClassB<3>);
  21. size_t b = sizeof(ClassB<7>);
  22. template <typename T> void FunctionA(T const& param)
  23. {
  24. }
  25. template <typename T> T FunctionB()
  26. {
  27. return T();
  28. }
  29. }
  30. // 1.1 Nested in Class
  31. namespace _1_1
  32. {
  33. template <typename T> // Old fasion: template <class T>
  34. class ClassA
  35. {
  36. T a;
  37. T* b;
  38. T foo();
  39. template <typename U> void foo2(T const&, U const&);
  40. };
  41. }
  42. // 1.2 Instanciating 1
  43. namespace _1_2
  44. {
  45. _1_1::ClassA<int> a;
  46. #if WRONG_CODE_ENABLED
  47. _1_1::ClassA<WhatTheFuck> b; // Wrong
  48. _1_1::ClassA c; // Wrong
  49. #endif
  50. }
  51. // 1.3 Instanciating 2
  52. namespace _1_3
  53. {
  54. template <typename T>
  55. class ClassB
  56. {
  57. T* a;
  58. };
  59. template <typename T>
  60. class ClassC
  61. {
  62. T a;
  63. };
  64. struct StructA; // Declared but not be defined
  65. ClassB<StructA> d; // Right
  66. #if WRONG_CODE_ENABLED
  67. ClassC<StructA> e; // Wrong
  68. #endif
  69. }
  70. // 1.4 Specialization, Partial Specialization, Full Specialization
  71. namespace _1_4
  72. {
  73. // Prototype of Templates I: Single Parameter
  74. template <typename T> class ClassD
  75. {
  76. int a;
  77. };
  78. // Specialization: Write a pattern for matching
  79. template <> class ClassD<int> // 1. template <> 2. ClassD<int>
  80. {
  81. int b;
  82. };
  83. template <> class ClassD<float>
  84. {
  85. int c;
  86. };
  87. // Partial-Specialization: A partial pattern for matching
  88. template <typename T> class ClassD<T*> // 1. template <typename T> 2. ClassD<T*>
  89. {
  90. int d;
  91. };
  92. template <> class ClassD<int*> // 1. template <> 2. ClassD<T*>
  93. {
  94. int e;
  95. };
  96. // Question:
  97. // ClassD<int>::?
  98. // ClassD<float>::?
  99. // ClassD<double>::?
  100. // ClassD<double*>::?
  101. // ClassD<int*>::?
  102. // ClassD<int const*>::?
  103. // Prototype of Templates II: Multiple Parameter
  104. template <typename T, typename U> class ClassE
  105. {
  106. int a;
  107. };
  108. template <typename T, typename U> class ClassE<T, U*>
  109. {
  110. int b;
  111. };
  112. template <typename T> class ClassE<T, int>
  113. {
  114. int c;
  115. };
  116. template <typename T> class ClassE<T, int*>
  117. {
  118. int d;
  119. };
  120. template <typename U> class ClassE<int, U>
  121. {
  122. int e;
  123. };
  124. template <> class ClassE<int, int>
  125. {
  126. int f;
  127. };
  128. // Question:
  129. // ClassE<float, double>::?
  130. // ClassE<float, int>::?
  131. // ClassE<int, float>::?
  132. // ClassE<int, int*>::?
  133. // ClassE<int, int>::?
  134. }
  135. // 2.1 Function Specialization
  136. namespace _2_1
  137. {
  138. // Overload is enabled but no partial-specialization
  139. template <typename T> void foo(T const& x) {}
  140. template <typename T> void foo(T& y) {}
  141. void foo(int&) {}
  142. void foo(int) {}
  143. // Specialization or Overloading
  144. template <> void foo<bool>(bool const& x) {}
  145. // Overloading
  146. template <typename T> void foo(T const*) {}
  147. template <typename T, typename U> void foo2(T const&, U const&);
  148. #if WRONG_CODE_ENABLED
  149. template <typename U> void foo2<int, U>(int const&, U const&);
  150. template <typename T, typename U> void foo2<T, U>(int const&, U const&);
  151. #endif
  152. // Overloading - Looks like partial specification
  153. template <typename U> void foo2(int const&, U const&);
  154. template <typename T, typename U> void foo2(T const*, U const&);
  155. // Don't forgot
  156. // T foo(...);
  157. // Specialize types which cannot be inferred by parameter
  158. template <typename UninferableT, typename InferableT>
  159. UninferableT foo3(InferableT const&) { return UninferableT(); }
  160. void test()
  161. {
  162. int x = 5;
  163. float y = 10.0f;
  164. foo(y);
  165. int const z = 5;
  166. foo(z);
  167. foo(true);
  168. foo3<int>(0.0f); // Specialize types which is uninferable.
  169. #if WRONG_CODE_ENABLED
  170. foo(3); // Ambigous
  171. foo(x); // Ambigous
  172. #endif
  173. }
  174. }
  175. // 2.2 Example: Derived from template.
  176. namespace _2_2
  177. {
  178. template <typename T>
  179. class ClassA
  180. {
  181. T x;
  182. };
  183. template <typename T>
  184. class ClassB
  185. {
  186. T* x;
  187. };
  188. template <typename T>
  189. class ClassC: public ClassB<T>
  190. {
  191. T* x;
  192. };
  193. ClassC<int> a;
  194. #if WRONG_CODE_ENABLED
  195. class ClassC: public ClassA<ClassC>
  196. {
  197. };
  198. #endif
  199. class ClassD: public ClassB<ClassD>
  200. {
  201. };
  202. // ClassC =??= ClassD
  203. }
  204. // 3.1 Meta Switch-Case/If-Then-Else via Specialization
  205. namespace _3_1
  206. {
  207. bool equal(int a, int b)
  208. {
  209. return a == b;
  210. }
  211. // meta functions:
  212. // bool equal0(TypeA, TypeB)
  213. // {
  214. // return false;
  215. // }
  216. // bool equal1(TypeA, TypeA)
  217. // {
  218. // return true;
  219. // }
  220. // equal(A, A) == equal1(A, A) == true
  221. // euqla(A, B) == equal0(A, B) == false
  222. template <typename T, typename U>
  223. class Equal
  224. {
  225. public:
  226. static bool const value = false;
  227. };
  228. template <typename T>
  229. class Equal<T, T>
  230. {
  231. public:
  232. static bool const value = true;
  233. };
  234. bool x = Equal<int, float>::value;
  235. bool y = Equal<int, int>::value;
  236. }
  237. // 3.2 SFINAE: Substitution Failure Is Not An Error.
  238. namespace _3_2
  239. {
  240. class ClassA
  241. {
  242. };
  243. template <int Sz> struct Mark
  244. {
  245. char _[Sz];
  246. };
  247. #if WRONG_CODE_ENABLED
  248. template <typename T>
  249. Mark<1> TestIncrementAdd(T const& v)
  250. {
  251. T tmp = v;
  252. ++tmp;
  253. return Mark<1>();
  254. }
  255. template <typename T>
  256. Mark<2> TestIncrementAdd(T const& v)
  257. {
  258. return Mark<2>();
  259. }
  260. bool a = TestIncrementAdd( ClassA() ) ) == sizeof(Mark<1>);
  261. #endif
  262. // Right case: From Wiki
  263. class ClassB
  264. {
  265. public:
  266. typedef int Marker;
  267. };
  268. template <typename T> void test(typename T::Marker) { }
  269. template <typename T> void test(T) { }
  270. void DoTest()
  271. {
  272. test<ClassB>(10); // Call #1.
  273. test<int>(10); // Call #2. SFINAE for test(T::Marker).
  274. }
  275. }
  276. // 3.3 Application: Type Traits
  277. namespace _3_3
  278. {
  279. template <typename T, typename U> class is_same;
  280. template <typename B, typename D> class is_base_of;
  281. // is_base_of
  282. // 1. B is class, D is also class.
  283. // 2. D* could be convert to B*
  284. // 3. B != D
  285. // Fundamentals
  286. typedef char Accepted;
  287. typedef int Rejected;
  288. class B
  289. {
  290. };
  291. class D: public B
  292. {
  293. };
  294. class D2: public D
  295. {
  296. };
  297. // Type is a class
  298. template <typename T>
  299. class is_class
  300. {
  301. private:
  302. // SFINAE
  303. template <typename U> static Accepted test( int U::* );
  304. template <typename U> static Rejected test(...);
  305. public:
  306. static const bool value = sizeof( test<T>(0) ) == sizeof(Accepted);
  307. };
  308. bool a = is_class<int>::value;
  309. bool b = is_class<B>::value;
  310. // B* could be convert to D*
  311. template <typename Source, typename Dest>
  312. class Convertible
  313. {
  314. private:
  315. // Not SFINAE
  316. static Accepted test(Dest*);
  317. static Rejected test(...);
  318. public:
  319. static const bool value = sizeof( test(static_cast<Source*>(NULL)) ) == sizeof(Accepted);
  320. };
  321. bool c = Convertible<B, D>::value;
  322. bool d = Convertible<D, B>::value;
  323. bool e = Convertible<B, int>::value;
  324. // B != D
  325. using _3_1::Equal;
  326. template <typename Base, typename Derived>
  327. class is_base_of
  328. {
  329. public:
  330. static bool const value =
  331. is_class<Base>::value &&
  332. is_class<Derived>::value &&
  333. Convertible<Base, Derived>::value &&
  334. !Equal<Base, Derived>::value;
  335. };
  336. bool f = is_base_of<B, D2>::value;
  337. bool g = is_base_of<D2, D>::value;
  338. bool h = is_base_of<B, int>::value;
  339. bool i = is_base_of<float, int>::value;
  340. // Questions:
  341. // remove_reference
  342. // remove_pointer
  343. // remove all qualifiers
  344. }
  345. // 3.4 Application: "Recursive" and Meta-Programming
  346. namespace _3_4
  347. {
  348. // sum a, a+1, ..., b-1, b
  349. int basic_algo(int a, int b)
  350. {
  351. int result = 0;
  352. for (int i = a; i <= b; ++i)
  353. {
  354. result += i;
  355. }
  356. return result;
  357. }
  358. // Template could not support variable
  359. // sum [a, b] without variable
  360. int recursive_algo(int a, int b)
  361. {
  362. if (a == b)
  363. {
  364. return b;
  365. }
  366. return a + recursive_algo(a+1, b);
  367. }
  368. // Translate to meta-programming
  369. template <int a, int b>
  370. class MetaSum
  371. {
  372. public:
  373. static int const value = MetaSum<a+1, b>::value + a;
  374. };
  375. template <int a>
  376. class MetaSum<a, a>
  377. {
  378. public:
  379. static int const value = a;
  380. };
  381. int a = MetaSum<1, 10>::value;
  382. }
  383. // 3.5 Application: Meta-Fibonacci
  384. namespace _3_5
  385. {
  386. template <int Index>
  387. class Fibonacci
  388. {
  389. public:
  390. static int const value = Fibonacci<Index - 1>::value + Fibonacci<Index - 2>::value;
  391. };
  392. template <>
  393. class Fibonacci<0>
  394. {
  395. public:
  396. static int const value = 0;
  397. };
  398. template <>
  399. class Fibonacci<1>
  400. {
  401. public:
  402. static int const value = 1;
  403. };
  404. int a = Fibonacci<8>::value;
  405. }
  406. // 4 Directive word: typename and template
  407. namespace _4
  408. {
  409. // typename T::type x;
  410. // ??? typename ???
  411. // typename T::template U<type> x;
  412. // ??? template ???
  413. class ClassA
  414. {
  415. public:
  416. typedef int NestedType;
  417. };
  418. class ClassB
  419. {
  420. public:
  421. typedef ClassA::NestedType NestedType;
  422. };
  423. template <typename T>
  424. class ClassC
  425. {
  426. public:
  427. #if WRONG_CODE_ENABLED
  428. typedef T::NestedType NestedType;
  429. #endif
  430. typedef typename T::NestedType NestedType;
  431. typedef typename std::vector<T>::iterator iterator;
  432. };
  433. class ClassD
  434. {
  435. public:
  436. template <typename U, typename V> class NestedType;
  437. };
  438. template <typename T>
  439. class ClassE
  440. {
  441. public:
  442. template <typename U> class NestedType;
  443. };
  444. template <typename T, typename U>
  445. class ClassF
  446. {
  447. #if WRONG_CODE_ENABLED
  448. typedef typename T::NestedType<U> NestedType;
  449. #endif
  450. typedef typename T::template NestedType<U, int> NestedType;
  451. typedef typename ClassE<T>::template NestedType<U> NestedType2;
  452. };
  453. ClassC<ClassB> a;
  454. ClassF<ClassD, float> b;
  455. }
  456. // 5.1 How to Construct Meta Operators
  457. namespace _5_1
  458. {
  459. // Expression = Value/Data Structure + Operator/Operations
  460. // Value in Templates:
  461. // Integral Constant (bool, char, unsigned, ...)
  462. // Type (typename)
  463. // 1. Trick: Constant <--> Type
  464. template <int i>
  465. class int_
  466. {
  467. public:
  468. static int const value = i;
  469. };
  470. int a = int_<5>::value;
  471. // This trick could work with overloading
  472. template <typename T>
  473. void Do(T* obj, int_<2>)
  474. {
  475. }
  476. template <typename T>
  477. void Do(T* obj, int_<1>)
  478. {
  479. }
  480. void foo()
  481. {
  482. Do( static_cast<int*>(nullptr), int_<1>() );
  483. }
  484. template <typename T, int i> void DoAnotherWay(T* obj)
  485. {
  486. }
  487. // Boolean is more useful than integral in general.
  488. template <bool v>
  489. class bool_
  490. {
  491. public:
  492. static bool const value = v;
  493. };
  494. typedef bool_<true> true_;
  495. typedef bool_<false> false_;
  496. #if WRONG_CODE_ENABLED
  497. // Aha, function cannot support partial specialization.
  498. template <typename T> void DoAnotherWay<T, 1>(T* obj) {}
  499. template <typename T> void DoAnotherWay<T, 2>(T* obj) {}
  500. #endif
  501. // 2. Operators:
  502. // add
  503. template <typename T, typename U>
  504. class add_
  505. {
  506. public:
  507. typedef int_<T::value + U::value> type;
  508. static int const value = type::value;
  509. };
  510. #if WRONG_CODE_ENABLED
  511. // conflict
  512. template <int x, int y>
  513. class add_
  514. {
  515. public:
  516. typedef int_<x+y> type;
  517. static int const value = type::value;
  518. };
  519. #endif
  520. template <int x, int y>
  521. class add_c
  522. {
  523. public:
  524. typedef int_<x+y> type;
  525. static int const value = type::value;
  526. };
  527. typedef add_< int_<2>, int_<3> >::type sum;
  528. int b = sum::value;
  529. typedef add_< int_<2>, int_<3> >::type sum_c;
  530. int c = sum_c::value;
  531. // another solution
  532. template <typename T, typename U>
  533. class add2_: public int_<T::value+U::value>
  534. {
  535. };
  536. int d = add2_< int_<2>, int_<3> >::value;
  537. // Other operators: sub, not, or, and ...
  538. }
  539. // 5.2 Example of Meta Programming: Meta-Vector
  540. namespace _5_2
  541. {
  542. // Array: elem[count]
  543. // Meta Array ?
  544. // Recursively Definition
  545. // 'Null' terminated
  546. template <typename HeadT, typename TailT>
  547. class pair_
  548. {
  549. typedef HeadT head;
  550. typedef TailT tail;
  551. };
  552. class Nil;
  553. // Try Use It to Definition
  554. typedef pair_< int, pair_<float, pair_<double, Nil> > > vector_3;
  555. template <typename T0, typename T1 = Nil, typename T2 = Nil, typename T3 = Nil>
  556. class make_vector_
  557. {
  558. typedef pair_< T0, make_vector_<T1, T2, T3> > type;
  559. };
  560. template <>
  561. class make_vector_<Nil, Nil, Nil, Nil>
  562. {
  563. typedef Nil type;
  564. };
  565. template <typename T0, typename T1 = Nil, typename T2 = Nil, typename T3 = Nil>
  566. class vector_: public make_vector_<T0, T1, T2, T3>::type
  567. {
  568. };
  569. typedef vector_<double, float, int> vector3;
  570. // Let's meta-program further
  571. //
  572. // push_back ? tip: push_back<Vector, Element>::type
  573. // pop ?
  574. // find ?
  575. // size ?
  576. }
  577. // 6.1 Template-Template Class
  578. // 6.2 High order function, closure and STL allocator rebind
  579. int _tmain(int argc, _TCHAR* argv[])
  580. {
  581. return 0;
  582. }