CppTemplateTutorial.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  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. // Member function specialization
  135. template <typename T>
  136. class ClassF
  137. {
  138. public:
  139. void foo();
  140. };
  141. template <typename T>
  142. void ClassF<T>::foo()
  143. {
  144. }
  145. template <>
  146. void ClassF<int>::foo()
  147. {
  148. }
  149. void foo()
  150. {
  151. ClassF<int>().foo();
  152. ClassF<float>().foo();
  153. }
  154. }
  155. // 2.1 Function Specialization
  156. namespace _2_1
  157. {
  158. // Overload is enabled but no partial-specialization
  159. template <typename T> void foo(T const& x) {}
  160. template <typename T> void foo(T& y) {}
  161. void foo(int&) {}
  162. void foo(int) {}
  163. // Specialization or Overloading
  164. template <> void foo<bool>(bool const& x) {}
  165. // Overloading
  166. template <typename T> void foo(T const*) {}
  167. template <typename T, typename U> void foo2(T const&, U const&);
  168. #if WRONG_CODE_ENABLED
  169. template <typename U> void foo2<int, U>(int const&, U const&);
  170. template <typename T, typename U> void foo2<T, U>(int const&, U const&);
  171. #endif
  172. // Overloading - Looks like partial specification
  173. template <typename U> void foo2(int const&, U const&);
  174. template <typename T, typename U> void foo2(T const*, U const&);
  175. // Don't forgot
  176. // T foo(...);
  177. // Specialize types which cannot be inferred by parameter
  178. template <typename UninferableT, typename InferableT>
  179. UninferableT foo3(InferableT const&) { return UninferableT(); }
  180. void test()
  181. {
  182. int x = 5;
  183. float y = 10.0f;
  184. foo(y);
  185. int const z = 5;
  186. foo(z);
  187. foo(true);
  188. foo3<int>(0.0f); // Specialize types which is uninferable.
  189. #if WRONG_CODE_ENABLED
  190. foo(3); // Ambigous
  191. foo(x); // Ambigous
  192. #endif
  193. }
  194. }
  195. // 2.2 Example: Derived from template.
  196. namespace _2_2
  197. {
  198. template <typename T>
  199. class ClassA
  200. {
  201. T x;
  202. };
  203. template <typename T>
  204. class ClassB
  205. {
  206. T* x;
  207. };
  208. template <typename T>
  209. class ClassC: public ClassB<T>
  210. {
  211. T* x;
  212. };
  213. ClassC<int> a;
  214. #if WRONG_CODE_ENABLED
  215. class ClassC: public ClassA<ClassC>
  216. {
  217. };
  218. #endif
  219. class ClassD: public ClassB<ClassD>
  220. {
  221. };
  222. // ClassC =??= ClassD
  223. }
  224. // 3.1 Meta Switch-Case/If-Then-Else via Specialization
  225. namespace _3_1
  226. {
  227. bool equal(int a, int b)
  228. {
  229. return a == b;
  230. }
  231. // meta functions:
  232. // bool equal0(TypeA, TypeB)
  233. // {
  234. // return false;
  235. // }
  236. // bool equal1(TypeA, TypeA)
  237. // {
  238. // return true;
  239. // }
  240. // equal(A, A) == equal1(A, A) == true
  241. // euqla(A, B) == equal0(A, B) == false
  242. template <typename T, typename U>
  243. class Equal
  244. {
  245. public:
  246. static bool const value = false;
  247. };
  248. template <typename T>
  249. class Equal<T, T>
  250. {
  251. public:
  252. static bool const value = true;
  253. };
  254. bool x = Equal<int, float>::value;
  255. bool y = Equal<int, int>::value;
  256. }
  257. // 3.2 SFINAE: Substitution Failure Is Not An Error.
  258. namespace _3_2
  259. {
  260. class ClassA
  261. {
  262. };
  263. template <int Sz> struct Mark
  264. {
  265. char _[Sz];
  266. };
  267. #if WRONG_CODE_ENABLED
  268. template <typename T>
  269. Mark<1> TestIncrementAdd(T const& v)
  270. {
  271. T tmp = v;
  272. ++tmp;
  273. return Mark<1>();
  274. }
  275. template <typename T>
  276. Mark<2> TestIncrementAdd(T const& v)
  277. {
  278. return Mark<2>();
  279. }
  280. bool a = TestIncrementAdd( ClassA() ) ) == sizeof(Mark<1>);
  281. #endif
  282. // Right case: From Wiki
  283. class ClassB
  284. {
  285. public:
  286. typedef int Marker;
  287. };
  288. template <typename T> void test(typename T::Marker) { }
  289. template <typename T> void test(T) { }
  290. void DoTest()
  291. {
  292. test<ClassB>(10); // Call #1.
  293. test<int>(10); // Call #2. SFINAE for test(T::Marker).
  294. }
  295. }
  296. // 3.3 Application: Type Traits
  297. namespace _3_3
  298. {
  299. template <typename T, typename U> class is_same;
  300. template <typename B, typename D> class is_base_of;
  301. // is_base_of
  302. // 1. B is class, D is also class.
  303. // 2. D* could be convert to B*
  304. // 3. B != D
  305. // Fundamentals
  306. typedef char Accepted;
  307. typedef int Rejected;
  308. class B
  309. {
  310. };
  311. class D: public B
  312. {
  313. };
  314. class D2: public D
  315. {
  316. };
  317. // Type is a class
  318. template <typename T>
  319. class is_class
  320. {
  321. private:
  322. // SFINAE
  323. template <typename U> static Accepted test( int U::* );
  324. template <typename U> static Rejected test(...);
  325. public:
  326. static const bool value = sizeof( test<T>(0) ) == sizeof(Accepted);
  327. };
  328. bool a = is_class<int>::value;
  329. bool b = is_class<B>::value;
  330. // B* could be convert to D*
  331. template <typename Source, typename Dest>
  332. class Convertible
  333. {
  334. private:
  335. // Not SFINAE
  336. static Accepted test(Dest*);
  337. static Rejected test(...);
  338. public:
  339. static const bool value = sizeof( test(static_cast<Source*>(NULL)) ) == sizeof(Accepted);
  340. };
  341. bool c = Convertible<B, D>::value;
  342. bool d = Convertible<D, B>::value;
  343. bool e = Convertible<B, int>::value;
  344. // B != D
  345. using _3_1::Equal;
  346. template <typename Base, typename Derived>
  347. class is_base_of
  348. {
  349. public:
  350. static bool const value =
  351. is_class<Base>::value &&
  352. is_class<Derived>::value &&
  353. Convertible<Base, Derived>::value &&
  354. !Equal<Base, Derived>::value;
  355. };
  356. bool f = is_base_of<B, D2>::value;
  357. bool g = is_base_of<D2, D>::value;
  358. bool h = is_base_of<B, int>::value;
  359. bool i = is_base_of<float, int>::value;
  360. // Questions:
  361. // remove_reference
  362. // remove_pointer
  363. // remove all qualifiers
  364. }
  365. // 3.4 Application: "Recursive" and Meta-Programming
  366. namespace _3_4
  367. {
  368. // sum a, a+1, ..., b-1, b
  369. int basic_algo(int a, int b)
  370. {
  371. int result = 0;
  372. for (int i = a; i <= b; ++i)
  373. {
  374. result += i;
  375. }
  376. return result;
  377. }
  378. // Template could not support variable
  379. // sum [a, b] without variable
  380. int recursive_algo(int a, int b)
  381. {
  382. if (a == b)
  383. {
  384. return b;
  385. }
  386. return a + recursive_algo(a+1, b);
  387. }
  388. // Translate to meta-programming
  389. template <int a, int b>
  390. class MetaSum
  391. {
  392. public:
  393. static int const value = MetaSum<a+1, b>::value + a;
  394. };
  395. template <int a>
  396. class MetaSum<a, a>
  397. {
  398. public:
  399. static int const value = a;
  400. };
  401. int a = MetaSum<1, 10>::value;
  402. }
  403. // 3.5 Application: Meta-Fibonacci
  404. namespace _3_5
  405. {
  406. template <int Index>
  407. class Fibonacci
  408. {
  409. public:
  410. static int const value = Fibonacci<Index - 1>::value + Fibonacci<Index - 2>::value;
  411. };
  412. template <>
  413. class Fibonacci<0>
  414. {
  415. public:
  416. static int const value = 0;
  417. };
  418. template <>
  419. class Fibonacci<1>
  420. {
  421. public:
  422. static int const value = 1;
  423. };
  424. int a = Fibonacci<8>::value;
  425. }
  426. // 4 Directive word: typename and template
  427. namespace _4
  428. {
  429. // typename T::type x;
  430. // ??? typename ???
  431. // typename T::template U<type> x;
  432. // ??? template ???
  433. class ClassA
  434. {
  435. public:
  436. typedef int NestedType;
  437. };
  438. class ClassB
  439. {
  440. public:
  441. typedef ClassA::NestedType NestedType;
  442. };
  443. template <typename T>
  444. class ClassC
  445. {
  446. public:
  447. #if WRONG_CODE_ENABLED
  448. typedef T::NestedType NestedType;
  449. #endif
  450. typedef typename T::NestedType NestedType;
  451. typedef typename std::vector<T>::iterator iterator;
  452. };
  453. class ClassD
  454. {
  455. public:
  456. template <typename U, typename V> class NestedType;
  457. };
  458. template <typename T>
  459. class ClassE
  460. {
  461. public:
  462. template <typename U> class NestedType;
  463. };
  464. template <typename T, typename U>
  465. class ClassF
  466. {
  467. #if WRONG_CODE_ENABLED
  468. typedef typename T::NestedType<U> NestedType;
  469. #endif
  470. typedef typename T::template NestedType<U, int> NestedType;
  471. typedef typename ClassE<T>::template NestedType<U> NestedType2;
  472. };
  473. ClassC<ClassB> a;
  474. ClassF<ClassD, float> b;
  475. }
  476. // 5.1 How to Construct Meta Operators
  477. namespace _5_1
  478. {
  479. // Expression = Value/Data Structure + Operator/Operations
  480. // Value in Templates:
  481. // Integral Constant (bool, char, unsigned, ...)
  482. // Type (typename)
  483. // 1. Trick: Constant <--> Type
  484. template <int i>
  485. class int_
  486. {
  487. public:
  488. static int const value = i;
  489. };
  490. int a = int_<5>::value;
  491. // This trick could work with overloading
  492. template <typename T>
  493. void Do(T* obj, int_<2>)
  494. {
  495. }
  496. template <typename T>
  497. void Do(T* obj, int_<1>)
  498. {
  499. }
  500. void foo()
  501. {
  502. Do( static_cast<int*>(nullptr), int_<1>() );
  503. }
  504. template <typename T, int i> void DoAnotherWay(T* obj)
  505. {
  506. }
  507. // Boolean is more useful than integral in general.
  508. template <bool v>
  509. class bool_
  510. {
  511. public:
  512. static bool const value = v;
  513. };
  514. typedef bool_<true> true_;
  515. typedef bool_<false> false_;
  516. #if WRONG_CODE_ENABLED
  517. // Aha, function cannot support partial specialization.
  518. template <typename T> void DoAnotherWay<T, 1>(T* obj) {}
  519. template <typename T> void DoAnotherWay<T, 2>(T* obj) {}
  520. #endif
  521. // 2. Operators:
  522. // add
  523. template <typename T, typename U>
  524. class add_
  525. {
  526. public:
  527. typedef int_<T::value + U::value> type;
  528. static int const value = type::value;
  529. };
  530. #if WRONG_CODE_ENABLED
  531. // conflict
  532. template <int x, int y>
  533. class add_
  534. {
  535. public:
  536. typedef int_<x+y> type;
  537. static int const value = type::value;
  538. };
  539. #endif
  540. template <int x, int y>
  541. class add_c
  542. {
  543. public:
  544. typedef int_<x+y> type;
  545. static int const value = type::value;
  546. };
  547. typedef add_< int_<2>, int_<3> >::type sum;
  548. int b = sum::value;
  549. typedef add_< int_<2>, int_<3> >::type sum_c;
  550. int c = sum_c::value;
  551. // another solution
  552. template <typename T, typename U>
  553. class add2_: public int_<T::value+U::value>
  554. {
  555. };
  556. int d = add2_< int_<2>, int_<3> >::value;
  557. // Other operators: sub, not, or, and ...
  558. }
  559. // 5.2 Example of Meta Programming: Meta-Vector
  560. namespace _5_2
  561. {
  562. // Array: elem[count]
  563. // Meta Array ?
  564. // Recursively Definition
  565. // 'Null' terminated
  566. template <typename HeadT, typename TailT>
  567. class pair_
  568. {
  569. typedef HeadT head;
  570. typedef TailT tail;
  571. };
  572. class Nil;
  573. // Try Use It to Definition
  574. typedef pair_< int, pair_<float, pair_<double, Nil> > > vector_3;
  575. template <typename T0, typename T1 = Nil, typename T2 = Nil, typename T3 = Nil>
  576. class make_vector_
  577. {
  578. typedef pair_< T0, make_vector_<T1, T2, T3> > type;
  579. };
  580. template <>
  581. class make_vector_<Nil, Nil, Nil, Nil>
  582. {
  583. typedef Nil type;
  584. };
  585. template <typename T0, typename T1 = Nil, typename T2 = Nil, typename T3 = Nil>
  586. class vector_: public make_vector_<T0, T1, T2, T3>::type
  587. {
  588. };
  589. typedef vector_<double, float, int> vector3;
  590. // Let's meta-program further
  591. //
  592. // push_back ? tip: push_back<Vector, Element>::type
  593. // pop ?
  594. // find ?
  595. // size ?
  596. }
  597. // 6.1 Template-Template Class
  598. // 6.2 High order function, closure and STL allocator rebind
  599. int _tmain(int argc, _TCHAR* argv[])
  600. {
  601. return 0;
  602. }