CppTemplateTutorial.cpp 13 KB

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