CppTemplateTutorial.cpp 12 KB

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