CppTemplateTutorial.cpp 13 KB

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