mirror of
https://github.com/wuye9036/CppTemplateTutorial.git
synced 2024-03-22 13:11:16 +08:00
Add list of content
Add part of sample code.
This commit is contained in:
commit
758bc2aefe
22
.gitattributes
vendored
Normal file
22
.gitattributes
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
*.sln merge=union
|
||||
*.csproj merge=union
|
||||
*.vbproj merge=union
|
||||
*.fsproj merge=union
|
||||
*.dbproj merge=union
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
163
.gitignore
vendored
Normal file
163
.gitignore
vendored
Normal file
|
@ -0,0 +1,163 @@
|
|||
#################
|
||||
## Eclipse
|
||||
#################
|
||||
|
||||
*.pydevproject
|
||||
.project
|
||||
.metadata
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.classpath
|
||||
.settings/
|
||||
.loadpath
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT-specific
|
||||
.cproject
|
||||
|
||||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
|
||||
#################
|
||||
## Visual Studio
|
||||
#################
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.vspscc
|
||||
.builds
|
||||
*.dotCover
|
||||
|
||||
## TODO: If you have NuGet Package Restore enabled, uncomment this
|
||||
#packages/
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish
|
||||
|
||||
# Others
|
||||
[Bb]in
|
||||
[Oo]bj
|
||||
sql
|
||||
TestResults
|
||||
*.Cache
|
||||
ClientBin
|
||||
stylecop.*
|
||||
~$*
|
||||
*.dbmdl
|
||||
Generated_Code #added for RIA/Silverlight projects
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
|
||||
|
||||
|
||||
############
|
||||
## Windows
|
||||
############
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
|
||||
#############
|
||||
## Python
|
||||
#############
|
||||
|
||||
*.py[co]
|
||||
|
||||
# Packages
|
||||
*.egg
|
||||
*.egg-info
|
||||
dist
|
||||
build
|
||||
eggs
|
||||
parts
|
||||
bin
|
||||
var
|
||||
sdist
|
||||
develop-eggs
|
||||
.installed.cfg
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
.coverage
|
||||
.tox
|
||||
|
||||
#Translations
|
||||
*.mo
|
||||
|
||||
#Mr Developer
|
||||
.mr.developer.cfg
|
||||
|
||||
# Mac crap
|
||||
.DS_Store
|
705
CppTemplateTutorial.cpp
Normal file
705
CppTemplateTutorial.cpp
Normal file
|
@ -0,0 +1,705 @@
|
|||
#include "stdafx.h"
|
||||
#include <vector>
|
||||
|
||||
#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.3 Instanciating 2
|
||||
namespace _1_3
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
// 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>::?
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
20
CppTemplateTutorial.sln
Normal file
20
CppTemplateTutorial.sln
Normal file
|
@ -0,0 +1,20 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppTemplateTutorial", "CppTemplateTutorial.vcxproj", "{E86AB3E9-316E-4D00-BBA3-B7CEDFA99D62}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E86AB3E9-316E-4D00-BBA3-B7CEDFA99D62}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{E86AB3E9-316E-4D00-BBA3-B7CEDFA99D62}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{E86AB3E9-316E-4D00-BBA3-B7CEDFA99D62}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{E86AB3E9-316E-4D00-BBA3-B7CEDFA99D62}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
89
CppTemplateTutorial.vcxproj
Normal file
89
CppTemplateTutorial.vcxproj
Normal file
|
@ -0,0 +1,89 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{E86AB3E9-316E-4D00-BBA3-B7CEDFA99D62}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>CppTemplateTutorial</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CppTemplateTutorial.cpp" />
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
33
CppTemplateTutorial.vcxproj.filters
Normal file
33
CppTemplateTutorial.vcxproj.filters
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CppTemplateTutorial.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
36
ReadMe.md
Normal file
36
ReadMe.md
Normal file
|
@ -0,0 +1,36 @@
|
|||
|
||||
# C++ Template 进阶指南
|
||||
|
||||
## 0. 前言
|
||||
|
||||
## 1. Template的基本语法
|
||||
|
||||
###1.1 Template Class的基本语法
|
||||
###1.2 Template Function的基本语法
|
||||
###1.3 整型也可是Template参数
|
||||
###1.4 类中类:灵活的模板定义
|
||||
|
||||
## 2. 模板世界的If-Then-Else:特化与偏特化
|
||||
###2.1 实例化/特化类模板:从类模板到可以定义变量的具体类
|
||||
###2.2 类模板的匹配规则:特化与部分特化
|
||||
###2.3 函数模板的重载、特化与部分特化
|
||||
###2.4 技巧单元:模板与继承
|
||||
|
||||
## 3 拿起特化的武器,去写程序吧!
|
||||
###3.1 利用模板特化规则实现If-Then-Else与Switch-Case
|
||||
###3.2 特化可以有多个选择:替换失败并不是一个错误,只是一种可能
|
||||
###3.3 技巧单元:获得类型的属性 ———— 类型萃取(Type Traits)
|
||||
|
||||
## 4 用模板写程序吧!骚年!
|
||||
## 4.1 模板上的递归
|
||||
## 4.2 实战单元:元编程的Fibonacci数列
|
||||
## 4.3 技巧单元:typename与template的另一种用法
|
||||
## 4.4 实战单元:撰写你自己的元编程“函数”库
|
||||
## 4.5 实战单元:实现元编程上的数据结构 ———— 以Vector为例
|
||||
|
||||
## 5 关于模板,你还需要知道的其它常识
|
||||
###5.1 Template-Template Class
|
||||
###5.2 技巧单元:高阶函数 ———— 从函数到函数的组合
|
||||
###5.3 实战单元:STL中的Allocator Rebinder
|
||||
|
||||
## 6 结语
|
8
stdafx.cpp
Normal file
8
stdafx.cpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// CppTemplateTutorial.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
15
stdafx.h
Normal file
15
stdafx.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
|
||||
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
8
targetver.h
Normal file
8
targetver.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
Loading…
Reference in New Issue
Block a user