123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911 |
- #include "stdafx.h"
- #include <vector>
- #include <cstdint>
- #define WRONG_CODE_ENABLED 0
- // 0. Basic Form
- namespace _0
- {
- template <typename T> // Old fasion: template <class T>
- class ClassA
- {
- T a;
- T* b;
- T foo();
- void foo2(T const&);
- };
- template <int Sz>
- class ClassB
- {
- int arr[Sz];
- };
- size_t a = sizeof(ClassB<3>);
- size_t b = sizeof(ClassB<7>);
- template <typename T> void FunctionA(T const& param)
- {
- }
- template <typename T> T FunctionB()
- {
- return T();
- }
- }
- // 1.1 Nested in Class
- namespace _1_1
- {
- template <typename T> // Old fasion: template <class T>
- class ClassA
- {
- T a;
- T* b;
- T foo();
- template <typename U> void foo2(T const&, U const&);
- };
- }
- // 1.2 Instanciating 1
- namespace _1_2
- {
- _1_1::ClassA<int> a;
- #if WRONG_CODE_ENABLED
- _1_1::ClassA<WhatTheFuck> b; // Wrong
- _1_1::ClassA c; // Wrong
- #endif
- }
- // 1.2.2
- namespace _1_2_2
- {
- template <typename T> T Add(T a, T b)
- {
- return a + b;
- }
- template <typename SrcT, typename DstT> DstT c_style_cast(SrcT v)
- {
- return (DstT)(v);
- }
- #if WRONG_CODE_ENABLED
- void foo()
- {
- int a = 0;
- int b = 0;
- char c = 0;
- Add(b, c);
- }
- void foo2()
- {
- int v = 0;
- float i = c_style_cast<float>(v);
- }
- #endif
- }
- // 1.3 Instanciating 2
- namespace _1_3
- {
- template <int i> class A
- {
- public:
- void foo()
- {
- }
- };
- template <uint8_t a, typename b, void* c> class B {};
- template <void (*a)()> class C {};
- template <void (A<3>::*a)()> class D {};
- #if WRONG_CODE_ENABLED
- template <float a> class E {};
- #endif
- void foo()
- {
- A<5> a;
- B<7, A<5>, nullptr> b;
- C<&foo> c;
- D<&A<3>::foo> d;
- #if WRONG_CODE_ENABLED
- int x = 3;
- A<x> b;
- #endif
- }
- #if WRONG_CODE_ENABLED
- const char* s = "abc";
- template <char const* s> class S
- {
- };
- void foo2()
- {
- S<"abc"> i;
- }
- #endif
- template <typename T>
- class ClassB
- {
- T* a;
- };
- template <typename T>
- class ClassC
- {
- T a;
- };
- struct StructA; // Declared but not be defined
- ClassB<StructA> d; // Right
- #if WRONG_CODE_ENABLED
- ClassC<StructA> e; // Wrong
- #endif
- }
- namespace _2_2_2
- {
- template <typename T> class AddFloatOrMulInt
- {
- static T Do(T a, T b)
- {
- // 在这个例子里面一般形式里面是什么内容不重要,因为用不上
- // 这里就随便给个0吧。
- return T(0);
- }
- };
- // 其次,我们要指定T是int时候的代码,这就是特化:
- template <> class AddFloatOrMulInt<int>
- {
- public:
- static int Do(int a, int b)
- {
- return a * b;
- }
- };
- // 再次,我们要指定T是float时候的代码:
- template <> class AddFloatOrMulInt<float>
- {
- public:
- static float Do(float a, float b)
- {
- return a * b;
- }
- };
- void foo()
- {
- float a(0), b(1);
- float c = AddFloatOrMulInt<float>::Do(a, b);
- }
- }
- namespace _2_2_3
- {
- template <typename T> class TypeToID
- {
- public:
- static int const ID = -1;
- };
- class B {};
- template <> class TypeToID<void ()>; // 函数的TypeID
- template <> class TypeToID<int[3]>; // 数组的TypeID
- template <> class TypeToID<int (int[3])>; // 这是以数组为参数的函数的TypeID
- template <> class TypeToID<int (B::*[3])(void*, float[2])>; // 我也不知道这是什么了,自己看着办吧。
- template <> class TypeToID<int const * volatile * const volatile>;
- }
- namespace _2_2_4
- {
- template <typename T> struct X {};
-
- template <typename T> struct Y
- {
- typedef X<T> ReboundType;
- #if WRONG_CODE_ENABLED
- typedef typename X<T>::MemberType MemberType;
- typedef WTF MemberType3;
- #endif
- static void foo()
- {
- X<T> instance0;
- typename X<T>::MemberType instance1;
- WTF instance2
- 大王叫我来巡山 - + &
- }
- };
- void foo()
- {
- #if WRONG_CODE_ENABLED
- Y<int>::foo();
- Y<float>::foo();
- #endif
- }
- }
- namespace _2_3_3 {
- struct A;
- template <typename T>
- struct X
- {
- void foo(T v) {
- A a;
- a.v = v;
- }
- };
- struct A
- {
- int v;
- };
- int foo2()
- {
- X<int> x;
- x.foo(5);
- return 0;
- }
- }
- // 1.4 Specialization, Partial Specialization, Full Specialization
- namespace _1_4
- {
- // Prototype of Templates I: Single Parameter
- template <typename T> class ClassD
- {
- int a;
- };
- // Specialization: Write a pattern for matching
- template <> class ClassD<int> // 1. template <> 2. ClassD<int>
- {
- int b;
- };
-
- template <> class ClassD<float>
- {
- int c;
- };
-
- // Partial-Specialization: A partial pattern for matching
- template <typename T> class ClassD<T*> // 1. template <typename T> 2. ClassD<T*>
- {
- int d;
- };
-
- template <> class ClassD<int*> // 1. template <> 2. ClassD<T*>
- {
- int e;
- };
-
- // Question:
-
- // ClassD<int>::?
- // ClassD<float>::?
- // ClassD<double>::?
- // ClassD<double*>::?
- // ClassD<int*>::?
- // ClassD<int const*>::?
-
- // Prototype of Templates II: Multiple Parameter
- template <typename T, typename U> class ClassE
- {
- int a;
- };
-
- template <typename T, typename U> class ClassE<T, U*>
- {
- int b;
- };
-
- template <typename T> class ClassE<T, int>
- {
- int c;
- };
-
- template <typename T> class ClassE<T, int*>
- {
- int d;
- };
-
- template <typename U> class ClassE<int, U>
- {
- int e;
- };
-
- template <> class ClassE<int, int>
- {
- int f;
- };
-
- // Question:
- // ClassE<float, double>::?
- // ClassE<float, int>::?
- // ClassE<int, float>::?
- // ClassE<int, int*>::?
- // ClassE<int, int>::?
- // Member function specialization
- template <typename T>
- class ClassF
- {
- public:
- void foo();
- };
- template <typename T>
- void ClassF<T>::foo()
- {
- }
- template <>
- void ClassF<int>::foo()
- {
- }
- void foo()
- {
- ClassF<int>().foo();
- ClassF<float>().foo();
- }
- }
- // 2.1 Function Specialization
- namespace _2_1
- {
- // Overload is enabled but no partial-specialization
- template <typename T> void foo(T const& x) {}
- template <typename T> void foo(T& y) {}
- void foo(int&) {}
- void foo(int) {}
- // Specialization or Overloading
- template <> void foo<bool>(bool const& x) {}
- // Overloading
- template <typename T> void foo(T const*) {}
- template <typename T, typename U> void foo2(T const&, U const&);
- #if WRONG_CODE_ENABLED
- template <typename U> void foo2<int, U>(int const&, U const&);
- template <typename T, typename U> void foo2<T, U>(int const&, U const&);
- #endif
- // Overloading - Looks like partial specification
- template <typename U> void foo2(int const&, U const&);
- template <typename T, typename U> void foo2(T const*, U const&);
- // Don't forgot
- // T foo(...);
- // Specialize types which cannot be inferred by parameter
- template <typename UninferableT, typename InferableT>
- UninferableT foo3(InferableT const&) { return UninferableT(); }
- void test()
- {
-
- int x = 5;
- float y = 10.0f;
- foo(y);
- int const z = 5;
- foo(z);
- foo(true);
- foo3<int>(0.0f); // Specialize types which is uninferable.
- #if WRONG_CODE_ENABLED
- foo(3); // Ambigous
- foo(x); // Ambigous
- #endif
- }
- }
- // 2.2 Example: Derived from template.
- namespace _2_2
- {
- template <typename T>
- class ClassA
- {
- T x;
- };
- template <typename T>
- class ClassB
- {
- T* x;
- };
-
- template <typename T>
- class ClassC: public ClassB<T>
- {
- T* x;
- };
-
- ClassC<int> a;
- #if WRONG_CODE_ENABLED
- class ClassC: public ClassA<ClassC>
- {
- };
- #endif
-
- class ClassD: public ClassB<ClassD>
- {
- };
-
- // ClassC =??= ClassD
- }
- // 3.1 Meta Switch-Case/If-Then-Else via Specialization
- namespace _3_1
- {
- bool equal(int a, int b)
- {
- return a == b;
- }
-
- // meta functions:
- // bool equal0(TypeA, TypeB)
- // {
- // return false;
- // }
- // bool equal1(TypeA, TypeA)
- // {
- // return true;
- // }
- // equal(A, A) == equal1(A, A) == true
- // euqla(A, B) == equal0(A, B) == false
- template <typename T, typename U>
- class Equal
- {
- public:
- static bool const value = false;
- };
-
- template <typename T>
- class Equal<T, T>
- {
- public:
- static bool const value = true;
- };
-
- bool x = Equal<int, float>::value;
- bool y = Equal<int, int>::value;
- }
- // 3.2 SFINAE: Substitution Failure Is Not An Error.
- namespace _3_2
- {
- class ClassA
- {
- };
- template <int Sz> struct Mark
- {
- char _[Sz];
- };
- #if WRONG_CODE_ENABLED
- template <typename T>
- Mark<1> TestIncrementAdd(T const& v)
- {
- T tmp = v;
- ++tmp;
- return Mark<1>();
- }
- template <typename T>
- Mark<2> TestIncrementAdd(T const& v)
- {
- return Mark<2>();
- }
- bool a = TestIncrementAdd( ClassA() ) ) == sizeof(Mark<1>);
- #endif
- // Right case: From Wiki
- class ClassB
- {
- public:
- typedef int Marker;
- };
-
- template <typename T> void test(typename T::Marker) { }
- template <typename T> void test(T) { }
-
- void DoTest()
- {
- test<ClassB>(10); // Call #1.
- test<int>(10); // Call #2. SFINAE for test(T::Marker).
- }
- }
- // 3.3 Application: Type Traits
- namespace _3_3
- {
- template <typename T, typename U> class is_same;
-
-
- template <typename B, typename D> class is_base_of;
- // is_base_of
- // 1. B is class, D is also class.
- // 2. D* could be convert to B*
- // 3. B != D
- // Fundamentals
- typedef char Accepted;
- typedef int Rejected;
- class B
- {
- };
- class D: public B
- {
- };
- class D2: public D
- {
- };
- // Type is a class
- template <typename T>
- class is_class
- {
- private:
- // SFINAE
- template <typename U> static Accepted test( int U::* );
- template <typename U> static Rejected test(...);
- public:
- static const bool value = sizeof( test<T>(0) ) == sizeof(Accepted);
- };
- bool a = is_class<int>::value;
- bool b = is_class<B>::value;
- // B* could be convert to D*
- template <typename Source, typename Dest>
- class Convertible
- {
- private:
- // Not SFINAE
- static Accepted test(Dest*);
- static Rejected test(...);
- public:
- static const bool value = sizeof( test(static_cast<Source*>(NULL)) ) == sizeof(Accepted);
- };
- bool c = Convertible<B, D>::value;
- bool d = Convertible<D, B>::value;
- bool e = Convertible<B, int>::value;
- // B != D
- using _3_1::Equal;
- template <typename Base, typename Derived>
- class is_base_of
- {
- public:
- static bool const value =
- is_class<Base>::value &&
- is_class<Derived>::value &&
- Convertible<Base, Derived>::value &&
- !Equal<Base, Derived>::value;
- };
- bool f = is_base_of<B, D2>::value;
- bool g = is_base_of<D2, D>::value;
- bool h = is_base_of<B, int>::value;
- bool i = is_base_of<float, int>::value;
- // Questions:
- // remove_reference
- // remove_pointer
- // remove all qualifiers
- }
- // 3.4 Application: "Recursive" and Meta-Programming
- namespace _3_4
- {
- // sum a, a+1, ..., b-1, b
- int basic_algo(int a, int b)
- {
- int result = 0;
- for (int i = a; i <= b; ++i)
- {
- result += i;
- }
- return result;
- }
- // Template could not support variable
- // sum [a, b] without variable
- int recursive_algo(int a, int b)
- {
- if (a == b)
- {
- return b;
- }
- return a + recursive_algo(a+1, b);
- }
- // Translate to meta-programming
- template <int a, int b>
- class MetaSum
- {
- public:
- static int const value = MetaSum<a+1, b>::value + a;
- };
- template <int a>
- class MetaSum<a, a>
- {
- public:
- static int const value = a;
- };
- int a = MetaSum<1, 10>::value;
- }
- // 3.5 Application: Meta-Fibonacci
- namespace _3_5
- {
- template <int Index>
- class Fibonacci
- {
- public:
- static int const value = Fibonacci<Index - 1>::value + Fibonacci<Index - 2>::value;
- };
- template <>
- class Fibonacci<0>
- {
- public:
- static int const value = 0;
- };
- template <>
- class Fibonacci<1>
- {
- public:
- static int const value = 1;
- };
- int a = Fibonacci<8>::value;
- }
- // 4 Directive word: typename and template
- namespace _4
- {
- // typename T::type x;
- // ??? typename ???
- // typename T::template U<type> x;
- // ??? template ???
- class ClassA
- {
- public:
- typedef int NestedType;
- };
- class ClassB
- {
- public:
- typedef ClassA::NestedType NestedType;
- };
- template <typename T>
- class ClassC
- {
- public:
- #if WRONG_CODE_ENABLED
- typedef T::NestedType NestedType;
- #endif
- typedef typename T::NestedType NestedType;
- typedef typename std::vector<T>::iterator iterator;
- };
- class ClassD
- {
- public:
- template <typename U, typename V> class NestedType;
- };
- template <typename T>
- class ClassE
- {
- public:
- template <typename U> class NestedType;
- };
- template <typename T, typename U>
- class ClassF
- {
- #if WRONG_CODE_ENABLED
- typedef typename T::NestedType<U> NestedType;
- #endif
- typedef typename T::template NestedType<U, int> NestedType;
- typedef typename ClassE<T>::template NestedType<U> NestedType2;
- };
- ClassC<ClassB> a;
- ClassF<ClassD, float> b;
- }
- // 5.1 How to Construct Meta Operators
- namespace _5_1
- {
- // Expression = Value/Data Structure + Operator/Operations
- // Value in Templates:
- // Integral Constant (bool, char, unsigned, ...)
- // Type (typename)
- // 1. Trick: Constant <--> Type
- template <int i>
- class int_
- {
- public:
- static int const value = i;
- };
- int a = int_<5>::value;
- // This trick could work with overloading
- template <typename T>
- void Do(T* obj, int_<2>)
- {
- }
- template <typename T>
- void Do(T* obj, int_<1>)
- {
- }
- void foo()
- {
- Do( static_cast<int*>(nullptr), int_<1>() );
- }
- template <typename T, int i> void DoAnotherWay(T* obj)
- {
- }
- // Boolean is more useful than integral in general.
- template <bool v>
- class bool_
- {
- public:
- static bool const value = v;
- };
- typedef bool_<true> true_;
- typedef bool_<false> false_;
-
- #if WRONG_CODE_ENABLED
- // Aha, function cannot support partial specialization.
- template <typename T> void DoAnotherWay<T, 1>(T* obj) {}
- template <typename T> void DoAnotherWay<T, 2>(T* obj) {}
- #endif
- // 2. Operators:
- // add
-
- template <typename T, typename U>
- class add_
- {
- public:
- typedef int_<T::value + U::value> type;
- static int const value = type::value;
- };
- #if WRONG_CODE_ENABLED
- // conflict
- template <int x, int y>
- class add_
- {
- public:
- typedef int_<x+y> type;
- static int const value = type::value;
- };
- #endif
- template <int x, int y>
- class add_c
- {
- public:
- typedef int_<x+y> type;
- static int const value = type::value;
- };
- typedef add_< int_<2>, int_<3> >::type sum;
- int b = sum::value;
- typedef add_< int_<2>, int_<3> >::type sum_c;
- int c = sum_c::value;
- // another solution
- template <typename T, typename U>
- class add2_: public int_<T::value+U::value>
- {
- };
- int d = add2_< int_<2>, int_<3> >::value;
- // Other operators: sub, not, or, and ...
- }
- // 5.2 Example of Meta Programming: Meta-Vector
- namespace _5_2
- {
- // Array: elem[count]
- // Meta Array ?
- // Recursively Definition
- // 'Null' terminated
- template <typename HeadT, typename TailT>
- class pair_
- {
- typedef HeadT head;
- typedef TailT tail;
- };
- class Nil;
-
- // Try Use It to Definition
- typedef pair_< int, pair_<float, pair_<double, Nil> > > vector_3;
- template <typename T0, typename T1 = Nil, typename T2 = Nil, typename T3 = Nil>
- class make_vector_
- {
- typedef pair_< T0, make_vector_<T1, T2, T3> > type;
- };
- template <>
- class make_vector_<Nil, Nil, Nil, Nil>
- {
- typedef Nil type;
- };
- template <typename T0, typename T1 = Nil, typename T2 = Nil, typename T3 = Nil>
- class vector_: public make_vector_<T0, T1, T2, T3>::type
- {
- };
- typedef vector_<double, float, int> vector3;
- // Let's meta-program further
- //
- // push_back ? tip: push_back<Vector, Element>::type
- // pop ?
- // find ?
- // size ?
- }
- // 6.1 Template-Template Class
- // 6.2 High order function, closure and STL allocator rebind
- int _tmain(int argc, _TCHAR* argv[])
- {
- return 0;
- }
|