CppTemplateTutorial.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  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. namespace _2_2_2
  132. {
  133. template <typename T> class AddFloatOrMulInt
  134. {
  135. static T Do(T a, T b)
  136. {
  137. // 在这个例子里面一般形式里面是什么内容不重要,因为用不上
  138. // 这里就随便给个0吧。
  139. return T(0);
  140. }
  141. };
  142. // 其次,我们要指定T是int时候的代码,这就是特化:
  143. template <> class AddFloatOrMulInt<int>
  144. {
  145. public:
  146. static int Do(int a, int b)
  147. {
  148. return a * b;
  149. }
  150. };
  151. // 再次,我们要指定T是float时候的代码:
  152. template <> class AddFloatOrMulInt<float>
  153. {
  154. public:
  155. static float Do(float a, float b)
  156. {
  157. return a * b;
  158. }
  159. };
  160. void foo()
  161. {
  162. float a(0), b(1);
  163. float c = AddFloatOrMulInt<float>::Do(a, b);
  164. }
  165. }
  166. namespace _2_2_3
  167. {
  168. template <typename T> class TypeToID
  169. {
  170. public:
  171. static int const ID = -1;
  172. };
  173. class B {};
  174. template <> class TypeToID<void ()>; // 函数的TypeID
  175. template <> class TypeToID<int[3]>; // 数组的TypeID
  176. template <> class TypeToID<int (int[3])>; // 这是以数组为参数的函数的TypeID
  177. template <> class TypeToID<int (B::*[3])(void*, float[2])>; // 我也不知道这是什么了,自己看着办吧。
  178. template <> class TypeToID<int const * volatile * const volatile>;
  179. }
  180. namespace _2_2_4
  181. {
  182. template <typename T> struct X {};
  183. template <typename T> struct Y
  184. {
  185. typedef X<T> ReboundType;
  186. #if WRONG_CODE_ENABLED
  187. typedef typename X<T>::MemberType MemberType;
  188. typedef WTF MemberType3;
  189. #endif
  190. static void foo()
  191. {
  192. X<T> instance0;
  193. typename X<T>::MemberType instance1;
  194. WTF instance2
  195. 大王叫我来巡山 - + &
  196. }
  197. };
  198. void foo()
  199. {
  200. #if WRONG_CODE_ENABLED
  201. Y<int>::foo();
  202. Y<float>::foo();
  203. #endif
  204. }
  205. }
  206. namespace _2_3_3 {
  207. struct A;
  208. template <typename T>
  209. struct X
  210. {
  211. void foo(T v) {
  212. A a;
  213. a.v = v;
  214. }
  215. };
  216. struct A
  217. {
  218. int v;
  219. };
  220. int foo2()
  221. {
  222. X<int> x;
  223. x.foo(5);
  224. return 0;
  225. }
  226. }
  227. // 1.4 Specialization, Partial Specialization, Full Specialization
  228. namespace _1_4
  229. {
  230. // Prototype of Templates I: Single Parameter
  231. template <typename T> class ClassD
  232. {
  233. int a;
  234. };
  235. // Specialization: Write a pattern for matching
  236. template <> class ClassD<int> // 1. template <> 2. ClassD<int>
  237. {
  238. int b;
  239. };
  240. template <> class ClassD<float>
  241. {
  242. int c;
  243. };
  244. // Partial-Specialization: A partial pattern for matching
  245. template <typename T> class ClassD<T*> // 1. template <typename T> 2. ClassD<T*>
  246. {
  247. int d;
  248. };
  249. template <> class ClassD<int*> // 1. template <> 2. ClassD<T*>
  250. {
  251. int e;
  252. };
  253. // Question:
  254. // ClassD<int>::?
  255. // ClassD<float>::?
  256. // ClassD<double>::?
  257. // ClassD<double*>::?
  258. // ClassD<int*>::?
  259. // ClassD<int const*>::?
  260. // Prototype of Templates II: Multiple Parameter
  261. template <typename T, typename U> class ClassE
  262. {
  263. int a;
  264. };
  265. template <typename T, typename U> class ClassE<T, U*>
  266. {
  267. int b;
  268. };
  269. template <typename T> class ClassE<T, int>
  270. {
  271. int c;
  272. };
  273. template <typename T> class ClassE<T, int*>
  274. {
  275. int d;
  276. };
  277. template <typename U> class ClassE<int, U>
  278. {
  279. int e;
  280. };
  281. template <> class ClassE<int, int>
  282. {
  283. int f;
  284. };
  285. // Question:
  286. // ClassE<float, double>::?
  287. // ClassE<float, int>::?
  288. // ClassE<int, float>::?
  289. // ClassE<int, int*>::?
  290. // ClassE<int, int>::?
  291. // Member function specialization
  292. template <typename T>
  293. class ClassF
  294. {
  295. public:
  296. void foo();
  297. };
  298. template <typename T>
  299. void ClassF<T>::foo()
  300. {
  301. }
  302. template <>
  303. void ClassF<int>::foo()
  304. {
  305. }
  306. void foo()
  307. {
  308. ClassF<int>().foo();
  309. ClassF<float>().foo();
  310. }
  311. }
  312. // 2.1 Function Specialization
  313. namespace _2_1
  314. {
  315. // Overload is enabled but no partial-specialization
  316. template <typename T> void foo(T const& x) {}
  317. template <typename T> void foo(T& y) {}
  318. void foo(int&) {}
  319. void foo(int) {}
  320. // Specialization or Overloading
  321. template <> void foo<bool>(bool const& x) {}
  322. // Overloading
  323. template <typename T> void foo(T const*) {}
  324. template <typename T, typename U> void foo2(T const&, U const&);
  325. #if WRONG_CODE_ENABLED
  326. template <typename U> void foo2<int, U>(int const&, U const&);
  327. template <typename T, typename U> void foo2<T, U>(int const&, U const&);
  328. #endif
  329. // Overloading - Looks like partial specification
  330. template <typename U> void foo2(int const&, U const&);
  331. template <typename T, typename U> void foo2(T const*, U const&);
  332. // Don't forgot
  333. // T foo(...);
  334. // Specialize types which cannot be inferred by parameter
  335. template <typename UninferableT, typename InferableT>
  336. UninferableT foo3(InferableT const&) { return UninferableT(); }
  337. void test()
  338. {
  339. int x = 5;
  340. float y = 10.0f;
  341. foo(y);
  342. int const z = 5;
  343. foo(z);
  344. foo(true);
  345. foo3<int>(0.0f); // Specialize types which is uninferable.
  346. #if WRONG_CODE_ENABLED
  347. foo(3); // Ambigous
  348. foo(x); // Ambigous
  349. #endif
  350. }
  351. }
  352. // 2.2 Example: Derived from template.
  353. namespace _2_2
  354. {
  355. template <typename T>
  356. class ClassA
  357. {
  358. T x;
  359. };
  360. template <typename T>
  361. class ClassB
  362. {
  363. T* x;
  364. };
  365. template <typename T>
  366. class ClassC: public ClassB<T>
  367. {
  368. T* x;
  369. };
  370. ClassC<int> a;
  371. #if WRONG_CODE_ENABLED
  372. class ClassC: public ClassA<ClassC>
  373. {
  374. };
  375. #endif
  376. class ClassD: public ClassB<ClassD>
  377. {
  378. };
  379. // ClassC =??= ClassD
  380. }
  381. // 3.1 Meta Switch-Case/If-Then-Else via Specialization
  382. namespace _3_1
  383. {
  384. bool equal(int a, int b)
  385. {
  386. return a == b;
  387. }
  388. // meta functions:
  389. // bool equal0(TypeA, TypeB)
  390. // {
  391. // return false;
  392. // }
  393. // bool equal1(TypeA, TypeA)
  394. // {
  395. // return true;
  396. // }
  397. // equal(A, A) == equal1(A, A) == true
  398. // euqla(A, B) == equal0(A, B) == false
  399. template <typename T, typename U>
  400. class Equal
  401. {
  402. public:
  403. static bool const value = false;
  404. };
  405. template <typename T>
  406. class Equal<T, T>
  407. {
  408. public:
  409. static bool const value = true;
  410. };
  411. bool x = Equal<int, float>::value;
  412. bool y = Equal<int, int>::value;
  413. }
  414. // 3.2 SFINAE: Substitution Failure Is Not An Error.
  415. namespace _3_2
  416. {
  417. class ClassA
  418. {
  419. };
  420. template <int Sz> struct Mark
  421. {
  422. char _[Sz];
  423. };
  424. #if WRONG_CODE_ENABLED
  425. template <typename T>
  426. Mark<1> TestIncrementAdd(T const& v)
  427. {
  428. T tmp = v;
  429. ++tmp;
  430. return Mark<1>();
  431. }
  432. template <typename T>
  433. Mark<2> TestIncrementAdd(T const& v)
  434. {
  435. return Mark<2>();
  436. }
  437. bool a = TestIncrementAdd( ClassA() ) ) == sizeof(Mark<1>);
  438. #endif
  439. // Right case: From Wiki
  440. class ClassB
  441. {
  442. public:
  443. typedef int Marker;
  444. };
  445. template <typename T> void test(typename T::Marker) { }
  446. template <typename T> void test(T) { }
  447. void DoTest()
  448. {
  449. test<ClassB>(10); // Call #1.
  450. test<int>(10); // Call #2. SFINAE for test(T::Marker).
  451. }
  452. }
  453. // 3.3 Application: Type Traits
  454. namespace _3_3
  455. {
  456. template <typename T, typename U> class is_same;
  457. template <typename B, typename D> class is_base_of;
  458. // is_base_of
  459. // 1. B is class, D is also class.
  460. // 2. D* could be convert to B*
  461. // 3. B != D
  462. // Fundamentals
  463. typedef char Accepted;
  464. typedef int Rejected;
  465. class B
  466. {
  467. };
  468. class D: public B
  469. {
  470. };
  471. class D2: public D
  472. {
  473. };
  474. // Type is a class
  475. template <typename T>
  476. class is_class
  477. {
  478. private:
  479. // SFINAE
  480. template <typename U> static Accepted test( int U::* );
  481. template <typename U> static Rejected test(...);
  482. public:
  483. static const bool value = sizeof( test<T>(0) ) == sizeof(Accepted);
  484. };
  485. bool a = is_class<int>::value;
  486. bool b = is_class<B>::value;
  487. // B* could be convert to D*
  488. template <typename Source, typename Dest>
  489. class Convertible
  490. {
  491. private:
  492. // Not SFINAE
  493. static Accepted test(Dest*);
  494. static Rejected test(...);
  495. public:
  496. static const bool value = sizeof( test(static_cast<Source*>(NULL)) ) == sizeof(Accepted);
  497. };
  498. bool c = Convertible<B, D>::value;
  499. bool d = Convertible<D, B>::value;
  500. bool e = Convertible<B, int>::value;
  501. // B != D
  502. using _3_1::Equal;
  503. template <typename Base, typename Derived>
  504. class is_base_of
  505. {
  506. public:
  507. static bool const value =
  508. is_class<Base>::value &&
  509. is_class<Derived>::value &&
  510. Convertible<Base, Derived>::value &&
  511. !Equal<Base, Derived>::value;
  512. };
  513. bool f = is_base_of<B, D2>::value;
  514. bool g = is_base_of<D2, D>::value;
  515. bool h = is_base_of<B, int>::value;
  516. bool i = is_base_of<float, int>::value;
  517. // Questions:
  518. // remove_reference
  519. // remove_pointer
  520. // remove all qualifiers
  521. }
  522. // 3.4 Application: "Recursive" and Meta-Programming
  523. namespace _3_4
  524. {
  525. // sum a, a+1, ..., b-1, b
  526. int basic_algo(int a, int b)
  527. {
  528. int result = 0;
  529. for (int i = a; i <= b; ++i)
  530. {
  531. result += i;
  532. }
  533. return result;
  534. }
  535. // Template could not support variable
  536. // sum [a, b] without variable
  537. int recursive_algo(int a, int b)
  538. {
  539. if (a == b)
  540. {
  541. return b;
  542. }
  543. return a + recursive_algo(a+1, b);
  544. }
  545. // Translate to meta-programming
  546. template <int a, int b>
  547. class MetaSum
  548. {
  549. public:
  550. static int const value = MetaSum<a+1, b>::value + a;
  551. };
  552. template <int a>
  553. class MetaSum<a, a>
  554. {
  555. public:
  556. static int const value = a;
  557. };
  558. int a = MetaSum<1, 10>::value;
  559. }
  560. // 3.5 Application: Meta-Fibonacci
  561. namespace _3_5
  562. {
  563. template <int Index>
  564. class Fibonacci
  565. {
  566. public:
  567. static int const value = Fibonacci<Index - 1>::value + Fibonacci<Index - 2>::value;
  568. };
  569. template <>
  570. class Fibonacci<0>
  571. {
  572. public:
  573. static int const value = 0;
  574. };
  575. template <>
  576. class Fibonacci<1>
  577. {
  578. public:
  579. static int const value = 1;
  580. };
  581. int a = Fibonacci<8>::value;
  582. }
  583. // 4 Directive word: typename and template
  584. namespace _4
  585. {
  586. // typename T::type x;
  587. // ??? typename ???
  588. // typename T::template U<type> x;
  589. // ??? template ???
  590. class ClassA
  591. {
  592. public:
  593. typedef int NestedType;
  594. };
  595. class ClassB
  596. {
  597. public:
  598. typedef ClassA::NestedType NestedType;
  599. };
  600. template <typename T>
  601. class ClassC
  602. {
  603. public:
  604. #if WRONG_CODE_ENABLED
  605. typedef T::NestedType NestedType;
  606. #endif
  607. typedef typename T::NestedType NestedType;
  608. typedef typename std::vector<T>::iterator iterator;
  609. };
  610. class ClassD
  611. {
  612. public:
  613. template <typename U, typename V> class NestedType;
  614. };
  615. template <typename T>
  616. class ClassE
  617. {
  618. public:
  619. template <typename U> class NestedType;
  620. };
  621. template <typename T, typename U>
  622. class ClassF
  623. {
  624. #if WRONG_CODE_ENABLED
  625. typedef typename T::NestedType<U> NestedType;
  626. #endif
  627. typedef typename T::template NestedType<U, int> NestedType;
  628. typedef typename ClassE<T>::template NestedType<U> NestedType2;
  629. };
  630. ClassC<ClassB> a;
  631. ClassF<ClassD, float> b;
  632. }
  633. // 5.1 How to Construct Meta Operators
  634. namespace _5_1
  635. {
  636. // Expression = Value/Data Structure + Operator/Operations
  637. // Value in Templates:
  638. // Integral Constant (bool, char, unsigned, ...)
  639. // Type (typename)
  640. // 1. Trick: Constant <--> Type
  641. template <int i>
  642. class int_
  643. {
  644. public:
  645. static int const value = i;
  646. };
  647. int a = int_<5>::value;
  648. // This trick could work with overloading
  649. template <typename T>
  650. void Do(T* obj, int_<2>)
  651. {
  652. }
  653. template <typename T>
  654. void Do(T* obj, int_<1>)
  655. {
  656. }
  657. void foo()
  658. {
  659. Do( static_cast<int*>(nullptr), int_<1>() );
  660. }
  661. template <typename T, int i> void DoAnotherWay(T* obj)
  662. {
  663. }
  664. // Boolean is more useful than integral in general.
  665. template <bool v>
  666. class bool_
  667. {
  668. public:
  669. static bool const value = v;
  670. };
  671. typedef bool_<true> true_;
  672. typedef bool_<false> false_;
  673. #if WRONG_CODE_ENABLED
  674. // Aha, function cannot support partial specialization.
  675. template <typename T> void DoAnotherWay<T, 1>(T* obj) {}
  676. template <typename T> void DoAnotherWay<T, 2>(T* obj) {}
  677. #endif
  678. // 2. Operators:
  679. // add
  680. template <typename T, typename U>
  681. class add_
  682. {
  683. public:
  684. typedef int_<T::value + U::value> type;
  685. static int const value = type::value;
  686. };
  687. #if WRONG_CODE_ENABLED
  688. // conflict
  689. template <int x, int y>
  690. class add_
  691. {
  692. public:
  693. typedef int_<x+y> type;
  694. static int const value = type::value;
  695. };
  696. #endif
  697. template <int x, int y>
  698. class add_c
  699. {
  700. public:
  701. typedef int_<x+y> type;
  702. static int const value = type::value;
  703. };
  704. typedef add_< int_<2>, int_<3> >::type sum;
  705. int b = sum::value;
  706. typedef add_< int_<2>, int_<3> >::type sum_c;
  707. int c = sum_c::value;
  708. // another solution
  709. template <typename T, typename U>
  710. class add2_: public int_<T::value+U::value>
  711. {
  712. };
  713. int d = add2_< int_<2>, int_<3> >::value;
  714. // Other operators: sub, not, or, and ...
  715. }
  716. // 5.2 Example of Meta Programming: Meta-Vector
  717. namespace _5_2
  718. {
  719. // Array: elem[count]
  720. // Meta Array ?
  721. // Recursively Definition
  722. // 'Null' terminated
  723. template <typename HeadT, typename TailT>
  724. class pair_
  725. {
  726. typedef HeadT head;
  727. typedef TailT tail;
  728. };
  729. class Nil;
  730. // Try Use It to Definition
  731. typedef pair_< int, pair_<float, pair_<double, Nil> > > vector_3;
  732. template <typename T0, typename T1 = Nil, typename T2 = Nil, typename T3 = Nil>
  733. class make_vector_
  734. {
  735. typedef pair_< T0, make_vector_<T1, T2, T3> > type;
  736. };
  737. template <>
  738. class make_vector_<Nil, Nil, Nil, Nil>
  739. {
  740. typedef Nil type;
  741. };
  742. template <typename T0, typename T1 = Nil, typename T2 = Nil, typename T3 = Nil>
  743. class vector_: public make_vector_<T0, T1, T2, T3>::type
  744. {
  745. };
  746. typedef vector_<double, float, int> vector3;
  747. // Let's meta-program further
  748. //
  749. // push_back ? tip: push_back<Vector, Element>::type
  750. // pop ?
  751. // find ?
  752. // size ?
  753. }
  754. // 6.1 Template-Template Class
  755. // 6.2 High order function, closure and STL allocator rebind
  756. int _tmain(int argc, _TCHAR* argv[])
  757. {
  758. return 0;
  759. }