#include "stdafx.h"
#include
#include
#define WRONG_CODE_ENABLED 0
// 0. Basic Form
namespace _0
{
template // Old fasion: template
class ClassA
{
T a;
T* b;
T foo();
void foo2(T const&);
};
template
class ClassB
{
int arr[Sz];
};
size_t a = sizeof(ClassB<3>);
size_t b = sizeof(ClassB<7>);
template void FunctionA(T const& param)
{
}
template T FunctionB()
{
return T();
}
}
// 1.1 Nested in Class
namespace _1_1
{
template // Old fasion: template
class ClassA
{
T a;
T* b;
T foo();
template void foo2(T const&, U const&);
};
}
// 1.2 Instanciating 1
namespace _1_2
{
_1_1::ClassA a;
#if WRONG_CODE_ENABLED
_1_1::ClassA b; // Wrong
_1_1::ClassA c; // Wrong
#endif
}
// 1.2.2
namespace _1_2_2
{
template T Add(T a, T b)
{
return a + b;
}
template 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(v);
}
#endif
}
// 1.3 Instanciating 2
namespace _1_3
{
template class A
{
public:
void foo()
{
}
};
template class B {};
template class C {};
template ::*a)()> class D {};
#if WRONG_CODE_ENABLED
template 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 b;
#endif
}
#if WRONG_CODE_ENABLED
const char* s = "abc";
template class S
{
};
void foo2()
{
S<"abc"> i;
}
#endif
template
class ClassB
{
T* a;
};
template
class ClassC
{
T a;
};
struct StructA; // Declared but not be defined
ClassB d; // Right
#if WRONG_CODE_ENABLED
ClassC e; // Wrong
#endif
}
namespace _2_2_2
{
template class AddFloatOrMulInt
{
static T Do(T a, T b)
{
// 在这个例子里面一般形式里面是什么内容不重要,因为用不上
// 这里就随便给个0吧。
return T(0);
}
};
// 其次,我们要指定T是int时候的代码,这就是特化:
template <> class AddFloatOrMulInt
{
public:
static int Do(int a, int b)
{
return a * b;
}
};
// 再次,我们要指定T是float时候的代码:
template <> class AddFloatOrMulInt
{
public:
static float Do(float a, float b)
{
return a * b;
}
};
void foo()
{
float a(0), b(1);
float c = AddFloatOrMulInt::Do(a, b);
}
}
namespace _2_2_3
{
template class TypeToID
{
public:
static int const ID = -1;
};
class B {};
template <> class TypeToID; // 函数的TypeID
template <> class TypeToID; // 数组的TypeID
template <> class TypeToID; // 这是以数组为参数的函数的TypeID
template <> class TypeToID; // 我也不知道这是什么了,自己看着办吧。
template <> class TypeToID;
}
namespace _2_2_4
{
template struct X {};
template struct Y
{
typedef X ReboundType;
#if WRONG_CODE_ENABLED
typedef typename X::MemberType MemberType;
typedef WTF MemberType3;
#endif
static void foo()
{
X instance0;
typename X::MemberType instance1;
WTF instance2
大王叫我来巡山 - + &
}
};
void foo()
{
#if WRONG_CODE_ENABLED
Y::foo();
Y::foo();
#endif
}
}
namespace _2_3_3 {
struct A;
template
struct X
{
void foo(T v) {
A a;
a.v = v;
}
};
struct A
{
int v;
};
int foo2()
{
X x;
x.foo(5);
return 0;
}
}
// 1.4 Specialization, Partial Specialization, Full Specialization
namespace _1_4
{
// Prototype of Templates I: Single Parameter
template class ClassD
{
int a;
};
// Specialization: Write a pattern for matching
template <> class ClassD // 1. template <> 2. ClassD
{
int b;
};
template <> class ClassD
{
int c;
};
// Partial-Specialization: A partial pattern for matching
template class ClassD // 1. template 2. ClassD
{
int d;
};
template <> class ClassD // 1. template <> 2. ClassD
{
int e;
};
// Question:
// ClassD::?
// ClassD::?
// ClassD::?
// ClassD::?
// ClassD::?
// ClassD::?
// Prototype of Templates II: Multiple Parameter
template class ClassE
{
int a;
};
template class ClassE
{
int b;
};
template class ClassE
{
int c;
};
template class ClassE
{
int d;
};
template class ClassE
{
int e;
};
template <> class ClassE
{
int f;
};
// Question:
// ClassE::?
// ClassE::?
// ClassE::?
// ClassE::?
// ClassE::?
// Member function specialization
template
class ClassF
{
public:
void foo();
};
template
void ClassF::foo()
{
}
template <>
void ClassF::foo()
{
}
void foo()
{
ClassF().foo();
ClassF().foo();
}
}
// 2.1 Function Specialization
namespace _2_1
{
// Overload is enabled but no partial-specialization
template void foo(T const& x) {}
template void foo(T& y) {}
void foo(int&) {}
void foo(int) {}
// Specialization or Overloading
template <> void foo(bool const& x) {}
// Overloading
template void foo(T const*) {}
template void foo2(T const&, U const&);
#if WRONG_CODE_ENABLED
template void foo2(int const&, U const&);
template void foo2(int const&, U const&);
#endif
// Overloading - Looks like partial specification
template void foo2(int const&, U const&);
template void foo2(T const*, U const&);
// Don't forgot
// T foo(...);
// Specialize types which cannot be inferred by parameter
template
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(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
class ClassA
{
T x;
};
template
class ClassB
{
T* x;
};
template
class ClassC: public ClassB
{
T* x;
};
ClassC a;
#if WRONG_CODE_ENABLED
class ClassC: public ClassA
{
};
#endif
class ClassD: public ClassB
{
};
// 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
class Equal
{
public:
static bool const value = false;
};
template
class Equal
{
public:
static bool const value = true;
};
bool x = Equal::value;
bool y = Equal::value;
}
// 3.2 SFINAE: Substitution Failure Is Not An Error.
namespace _3_2
{
class ClassA
{
};
template struct Mark
{
char _[Sz];
};
#if WRONG_CODE_ENABLED
template
Mark<1> TestIncrementAdd(T const& v)
{
T tmp = v;
++tmp;
return Mark<1>();
}
template
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 void test(typename T::Marker) { }
template void test(T) { }
void DoTest()
{
test(10); // Call #1.
test(10); // Call #2. SFINAE for test(T::Marker).
}
}
// 3.3 Application: Type Traits
namespace _3_3
{
template class is_same;
template 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
class is_class
{
private:
// SFINAE
template static Accepted test( int U::* );
template static Rejected test(...);
public:
static const bool value = sizeof( test(0) ) == sizeof(Accepted);
};
bool a = is_class::value;
bool b = is_class::value;
// B* could be convert to D*
template
class Convertible
{
private:
// Not SFINAE
static Accepted test(Dest*);
static Rejected test(...);
public:
static const bool value = sizeof( test(static_cast(NULL)) ) == sizeof(Accepted);
};
bool c = Convertible::value;
bool d = Convertible::value;
bool e = Convertible::value;
// B != D
using _3_1::Equal;
template
class is_base_of
{
public:
static bool const value =
is_class::value &&
is_class::value &&
Convertible::value &&
!Equal::value;
};
bool f = is_base_of::value;
bool g = is_base_of::value;
bool h = is_base_of::value;
bool i = is_base_of::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
class MetaSum
{
public:
static int const value = MetaSum::value + a;
};
template
class MetaSum
{
public:
static int const value = a;
};
int a = MetaSum<1, 10>::value;
}
// 3.5 Application: Meta-Fibonacci
namespace _3_5
{
template
class Fibonacci
{
public:
static int const value = Fibonacci::value + Fibonacci::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 x;
// ??? template ???
class ClassA
{
public:
typedef int NestedType;
};
class ClassB
{
public:
typedef ClassA::NestedType NestedType;
};
template
class ClassC
{
public:
#if WRONG_CODE_ENABLED
typedef T::NestedType NestedType;
#endif
typedef typename T::NestedType NestedType;
typedef typename std::vector::iterator iterator;
};
class ClassD
{
public:
template class NestedType;
};
template
class ClassE
{
public:
template class NestedType;
};
template
class ClassF
{
#if WRONG_CODE_ENABLED
typedef typename T::NestedType NestedType;
#endif
typedef typename T::template NestedType NestedType;
typedef typename ClassE::template NestedType NestedType2;
};
ClassC a;
ClassF 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
class int_
{
public:
static int const value = i;
};
int a = int_<5>::value;
// This trick could work with overloading
template
void Do(T* obj, int_<2>)
{
}
template
void Do(T* obj, int_<1>)
{
}
void foo()
{
Do( static_cast(nullptr), int_<1>() );
}
template void DoAnotherWay(T* obj)
{
}
// Boolean is more useful than integral in general.
template
class bool_
{
public:
static bool const value = v;
};
typedef bool_ true_;
typedef bool_ false_;
#if WRONG_CODE_ENABLED
// Aha, function cannot support partial specialization.
template void DoAnotherWay(T* obj) {}
template void DoAnotherWay(T* obj) {}
#endif
// 2. Operators:
// add
template
class add_
{
public:
typedef int_<:value u::value> type;
static int const value = type::value;
};
#if WRONG_CODE_ENABLED
// conflict
template
class add_
{
public:
typedef int_ type;
static int const value = type::value;
};
#endif
template
class add_c
{
public:
typedef int_ 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
class add2_: public int_<: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
class pair_
{
typedef HeadT head;
typedef TailT tail;
};
class Nil;
// Try Use It to Definition
typedef pair_< int, pair_ > > vector_3;
template
class make_vector_
{
typedef pair_< T0, make_vector_ > type;
};
template <>
class make_vector_
{
typedef Nil type;
};
template
class vector_: public make_vector_::type
{
};
typedef vector_ vector3;
// Let's meta-program further
//
// push_back ? tip: push_back::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;
}