C++模板从入门到入土
1. 函数模板的调用和参数推导
cpp
#include <iostream>
using namespace std;
double func1(double a, double b) {
return a + b;
}
template<class T>
T funcT1(T a, T b) {
return a + b;
}
template<class T>
void funcT2() {
cout << "funcT2" << endl;
}
template<class T1, class T2, class T3>
T3 funcT3(T1 a, T2 b) {
return a + b;
}
template<class T3, class T1, class T2>
T3 funcT4(T1 a, T2 b) {
return a + b;
}
int main() {
int a = 1;
int b = 2;
double c = 1.1;
double d = 2.2;
char e = 'e';
string f = "f";
cout << funcT1(a, b) << endl;
cout << funcT1<>(a, b) << endl;
cout << funcT1<int>(a, c) << endl;
cout << funcT1<double>(a, c) << endl;
funcT2<int>();
cout << funcT3<int, int, int>(a, b) << endl;
cout << funcT4<int>(a, b) << endl;
cout << func1(a, e) << endl;
return 0;
}
输出:
text
3
3
2
2.1
funcT2
3
3
2. 函数模板的重载
cpp
#include <iostream>
using namespace std;
int func1(int a, int b) {
cout << "这是普通函数 func1" << endl;
return a + b;
}
template<class T>
T func1(T a, T b) {
cout << "这是函数模板 func1" << endl;
return a + b;
}
void func2() {
cout << "这是普通函数 func2" << endl;
}
template<class T>
void func2() {
cout << "这是函数模板 func2" << endl;
}
template<class T>
void func3(T a, T b) {
cout << "这是函数模板 func3" << endl;
}
template<class T>
void func3(T* a, T* b) {
cout << (a + b) << endl;
cout << "这是函数模板 *func3" << endl;
}
template<class T>
void func4(T a, T b) {
cout << "这是函数模板 func4-两个参数" << endl;
}
template<class T>
void func4(T a) {
cout << "这是函数模板 func4-一个参数" << endl;
}
int main() {
int a = 1;
int b = 2;
double c = 1.1;
double d = 2.2;
func1<>(a, b);
func1(a, b);
func1<int>(a, b);
func1<>(a, b);
func1(c, d);
func2();
func2<int>();
func3(a, b);
func4(a);
func4(a, a);
return 0;
}
输出:
text
这是函数模板 func1
这是普通函数 func1
这是函数模板 func1
这是函数模板 func1
这是函数模板 func1
这是普通函数 func2
这是函数模板 func2
这是函数模板 func3
这是函数模板 func4-一个参数
这是函数模板 func4-两个参数
3. 函数模板的参数默认值
cpp
#include <iostream>
using namespace std;
template<class T1, class T2 = int>
void funcT1(T1 a, T2 b = 123) {
cout << a << "--" << typeid(a).name() << endl;
cout << b << "--" << typeid(b).name() << endl;
}
template<class T1 = int, class T2>
void funcT2(T2 b) {
T1 a = b;
cout << b << "--" << a << endl;
}
template<class T1, int T2 = 12>
void funcT3(T1 a) {
cout << a << "--" << T2 << endl;
}
int main() {
int a = 1;
int b = 2;
double c = 1.1;
double d = 2.2;
funcT1(a);
funcT2(c);
funcT2<double>(c);
funcT3(a);
int const x = 789;
funcT3<int, x>(a);
return 0;
}
输出:
text
1--int
123--int
1.1--1
1.1--1.1
1--12
1--789
4. 函数模板的泛化与特化
cpp
#include <iostream>
using namespace std;
template<class T1, class T2>
void funcT1(T1 a, T2 b) {
cout << "这里是函数模板funcT1" << endl;
}
template<>
void funcT1<int, double>(int a, double b) {
cout << "这里是函数模板特化-int--double--funcT1" << endl;
}
template<class T1 = int, class T2>
void funcT1(int a, T2 b) {
cout << "这里是函数局部模板特化-int--double--funcT1" << endl;
}
void funcT1(int a, double b) {
cout << "这里是函数重载-int--double--funcT1" << endl;
}
int main() {
int a = 1;
int b = 2;
double c = 1.1;
double d = 2.2;
funcT1(a, b);
funcT1(c, d);
funcT1(a, c);
funcT1(c, a);
return 0;
}
输出:
text
这里是函数局部模板特化-int--double--funcT1
这里是函数模板funcT1
这里是函数重载-int--double--funcT1
这里是函数模板funcT1
5. 类模板的定义和调用
cpp
#include <iostream>
#include<string>
using namespace std;
class C1 {
public:
C1(int id, string name) {
this->id = id;
this->name = name;
}
~C1() {}
void show() {
cout << id << "--" << name << endl;
}
static void func1() {
cout << "这里是 c1-func1" << endl;
}
int id;
string name;
};
template<class T1, class T2>
class C2 {
public:
C2(T1 id, T2 name) {
this->id = id;
this->name = name;
}
~C2() {}
void show() {
cout << id << "--" << name << endl;
}
static void func1() {
cout << "这里是 c2-func1" << endl;
}
T1 id;
T2 name;
};
template<class T1 = int, class T2 = string>
class C3 {
public:
C3(T1 id = 456, T2 name = "jerry") {
this->id = id;
this->name = name;
}
~C3() {}
void show() {
cout << id << "--" << name << endl;
}
static void func1() {
cout << "这里是 c2-func1" << endl;
}
T1 id;
T2 name;
};
int main() {
C1 c1(123, "tom");
c1.show();
c1.func1();
C1::func1();
C2<int, string>c2(123, "tom");
c2.show();
c2.func1();
C2<int, int>::func1();
C3<int, int>c3(123, 456);
c3.show();
C3<string, string>c4("tom", "tom");
c4.show();
C3<>::func1();
return 0;
}
输出:
text
123--tom
这里是 c1-func1
这里是 c1-func1
123--tom
这里是 c2-func1
这里是 c2-func1
123--456
tom--tom
这里是 c2-func1
6. 类模板中的参数推导
cpp
#include <iostream>
#include<string>
using namespace std;
template<class T1, class T2>
class C1 {
public:
C1(T1 id, T2 name) {
this->id = id;
this->name = name;
}
T1 id;
T2 name;
};
template<class T1, class T2>
class C2 {
public:
C2(T1 id, T2 name) {
this->id = id;
this->name = name;
}
T1 id;
T2 name;
};
template<class T1, class T2>
class C3 {
public:
T1 id;
T2 name;
};
template<class T1, class T2>
class C4 {
public:
T1 id;
T2 name;
};
template<class T1, class T2>
C4(T1, T2)->C4<T1, T2>;
template<class T1, class T2>
struct S1 {
T1 id;
T2 name;
};
template<class T1, class T2>
S1(T1, T2)->S1<T1, T2>;
int main() {
C1<int, string> c1(123, "tom");
cout << c1.id << "--" << c1.name << endl;
C2 c2(123, "tom");
cout << c2.id << "--" << c2.name << endl;
C3<int, string>c3;
c3.id = 123;
c3.name = "tom";
cout << c3.id << "--" << c3.name << endl;
C4 c4{ 123,"tom" };
cout << c4.id << "--" << c4.name << endl;
S1 s1{ "tom","tom" };
cout << s1.id << "--" << s1.name << endl;
return 0;
}
输出:
text
123--tom
123--tom
123--tom
123--tom
tom--tom
7. 类模板的编译规则
cpp
#include <iostream>
using namespace std;
template<class T1, class T2>
class C1 {
public:
C1(T1 id, T2 name) {
this->id = id;
this->name = name;
}
void func1() {
cout << "func1" << endl;
}
static void func2() {
cout << "static func2" << endl;
}
T1 id;
T2 name;
};
int main() {
C1<int, int>c1(123, 456);
c1.func1();
C1<double, double> c11(1.1, 1.1);
c11.func2();
return 0;
}
输出:
text
func1
static func2
8. 类模板的参数默认值
cpp
#include <iostream>
#include<string>
using namespace std;
template<class T1, class T2 = string>
class C1 {
public:
C1(T1 id, T2 name) {
this->id = id;
this->name = name;
}
T1 id;
T2 name;
};
template<class T1>
class C1<T1, string> {
public:
C1(T1 id, string name) {
this->id = id;
this->name = name;
cout << "这里是局部特化" << endl;
}
T1 id;
string name;
};
template<class T1, class T2 = T1*>
class C2 {
public:
C2(T1 id, T2 name) {
this->id = id;
this->name = name;
}
T1 id;
T2 name;
};
template<class T1 = int, class T2 = int>
class C3 {
public:
C3(T1, T2);
T1 id;
T2 name;
};
template<class T1, class T2>
C3<T1, T2>::C3(T1 id, T2 name) {
this->id = id;
this->name = name;
}
template<class T1, class T2, class T3 = int>
struct S1;
template<class T1, class T2 = int, class T3>
struct S1;
template<class T1, class T2, class T3>
struct S1 {
T1 id;
T2 name;
T3 sex;
};
int main() {
C1<int, string>c1(123, "tom");
C1<int>c111(123, "tom");
C1<int>c1111(123, "tom");
cout << c1111.id << "--" << c1111.name << endl;
int a = 123;
C2<int>c2(a, &a);
cout << c2.id << "--" << c2.name << endl;
C3<>c3(1.1, 2.2);
cout << c3.id << "--" << c3.name << endl;
S1<int>s1;
s1.id = 1;
s1.name = 2;
s1.sex = 3;
cout << s1.id << "--" << s1.name << "--" << s1.sex << endl;
return 0;
}
输出:
text
这里是局部特化
这里是局部特化
这里是局部特化
123--tom
123--0000007139DEF284
1--2
1--2--3
9. 类模板的泛化与特化
cpp
#include <iostream>
#include<string>
using namespace std;
template<class T1, class T2>
class C1 {
public:
C1() {
cout << "这里是C1-构造" << endl;
}
void func1() {
cout << "这里是C1-func1" << endl;
}
static int flag;
};
template<class T1, class T2>
int C1<T1, T2>::flag = 123;
template<>
void C1<int, int>::func1() {
cout << "这里是C1-func1-全特化-int-int" << endl;
}
template<>
int C1<double, double>::flag = 456;
template<>
class C1<int, string> {
public:
C1() {
cout << "这里是C1-全特化-构造" << endl;
}
void func1() {
cout << "这里是C1-全特化-func1" << endl;
}
void func2() {
cout << "这里是C1-全特化-func2" << endl;
}
};
template<class T1>
class C1<T1, string> {
public:
C1() {
cout << "这里是C1-半特化-T1-string-构造" << endl;
}
void func1() {
cout << "这里是C1-半特化-T1-string-func1" << endl;
}
void func2() {
cout << "这里是C1-半特化-T1-string-func2" << endl;
}
};
template<class T1, class T2>
class C1<const T1, T2*> {
public:
C1() {
cout << "这里是C1-参数范围特化-const T1-T2 *-构造" << endl;
}
void func1(){
cout<<"这里是C1-半特化-T1-string-func1"<<endl;
}
void func2(){
cout<<"这里是C1-半特化-T1-string-func2"<<endl;
}
};
int main() {
C1<int, string>c1;
c1.func1();
cout << endl;
C1<int, int>c11;
c11.func1();
C1<double, double>c111;
cout << c111.flag << endl;
C1<int, double>c123;
c123.func1();
C1<int, string>c112;
c112.func1();
c112.func2();
C1<string, string>c1112;
c1112.func1();
c1112.func2();
C1<const int, int*>c1111;
c1111.func1();
C1<string, int>c11122;
c11122.func1();
return 0;
}
输出:
text
这里是C1-全特化-构造
这里是C1-全特化-func1
这里是C1-构造
这里是C1-func1-全特化-int-int
这里是C1-构造
456
这里是C1-构造
这里是C1-func1
这里是C1-全特化-构造
这里是C1-全特化-func1
这里是C1-全特化-func2
这里是C1-半特化-T1-string-构造
这里是C1-半特化-T1-string-func1
这里是C1-半特化-T1-string-func2
这里是C1-参数范围特化-const T1-T2 *-构造
这里是C1-半特化-T1-string-func1
这里是C1-构造
这里是C1-func1
10. 成员函数模板
cpp
#include <iostream>
using namespace std;
template<class T1>
class C1 {
public:
C1() {
cout << "构造" << endl;
}
template<class T2>
void func2(T2 id) {
cout << "func2-类内实现-泛化-T2-id-" << id << endl;
}
template<class T3>
void func3(T3 name);
void func3(int name);
void func3(string name) {
cout << "func3-类内实现-特化-string-name-" << name << endl;
}
void func3(T1 name) {
cout << "func3-类内实现-特化-T1-name-" << name << endl;
}
virtual void func4(int age) {}
virtual void func5(T1 age) {}
};
template<class T1>
template<class T3>
void C1<T1>::func3(T3 name) {
cout << "func3-类外实现-泛化-T3-name-" << name << endl;
};
template<class T1>
void C1<T1>::func3(int name) {
cout << "func3-类外实现-特化-int-name-" << name << endl;
};
int main() {
C1<double>c1;
c1.func2(123);
c1.func3(1.23);
c1.func3("123");
string str = "str";
c1.func3(str);
C1<char>c11;
c11.func3('1');
C1<float>c111;
c111.func3(1.1f);
return 0;
}
输出:
text
构造
func2-类内实现-泛化-T2-id-123
func3-类内实现-特化-T1-name-1.23
func3-类外实现-泛化-T3-name-123
func3-类内实现-特化-string-name-str
构造
func3-类内实现-特化-T1-name-1
构造
func3-类内实现-特化-T1-name-1.1
11. 拷贝构造函数模板
cpp
#include <iostream>
using namespace std;
class C1 {
public:
C1() {
cout << "这里是构造" << endl;
}
C1(const C1& c2) {
cout << "这里是拷贝构造" << endl;
}
C1& operator=(const C1& c2) {
cout << "这里是拷贝符值运算符重载" << endl;
return *this;
}
};
template<class T1>
class C2 {
public:
C2() {
cout << "这里是构造" << endl;
}
template<class T2>
C2(const C2<T2>& c2) {
cout << "这里是拷贝构造" << endl;
}
C2(const C2<float>& c2) {
cout << "这里是拷贝构造-特化-float" << endl;
}
template<class T3>
C2<T1>& operator=(const C2<T3>& c2) {
cout << "这里是拷贝符值运算符重载" << endl;
return *this;
}
int id;
};
int main() {
C2<float>c2F;
C2<int>c2Int(c2F);
C2<int>c2;
c2.id=123;
C2<int>c22(c2);
cout<<c22.id<<endl;
C2<double>c222(c2);
cout<<c222.id<<endl;
C2<int>c2222;
c2222=c2;
cout<<c2222.id<<endl;
C2<double>c22222;
c22222=c2;
C1 c1;
C1 c11(c1);
C1 c111;
c111=c1;
return 0;
}
输出:
text
这里是构造
这里是拷贝构造-特化-float
这里是构造
123
这里是拷贝构造
-858993460
这里是构造
123
这里是构造
这里是拷贝符值运算符重载
这里是构造
这里是拷贝构造
这里是构造
这里是拷贝符值运算符重载
12. 类模板中的嵌套
cpp
#include <iostream>
using namespace std;
template<class T1>
class C1 {
public:
void func1() {
cout << "C1-T1-func1" << endl;
}
template<class T2>
class C2 {
public:
void func1() {
cout << "C1-T1---C2-T2-func1" << endl;
}
};
template<>
class C2<int> {
public:
void func1() {
cout << "C1-T1---C2-int-func1" << endl;
}
};
};
template<>
class C1<double> {
public:
template<class T2>
class C2 {
public:
void func1() {
cout << "C1-double---C2-T2-func1" << endl;
}
};
};
template<>
template<>
class C1<float>::C2<float> {
public:
void func1() {
cout << "C1-float---C2-float-func1" << endl;
}
};
int main() {
C1<int>::C2<double>C1T1C2T2;
C1T1C2T2.func1();
C1<int>::C2<int>C1T1C2Int;
C1T1C2Int.func1();
C1<double>::C2<int>C1DoubleC2T2;
C1DoubleC2T2.func1();
C1<float>::C2<float>C1FloatC2Float;
C1FloatC2Float.func1();
return 0;
}
输出:
text
C1-T1---C2-T2-func1
C1-T1---C2-int-func1
C1-double---C2-T2-func1
C1-float---C2-float-func1
13. 类模板中的友元
cpp
#include <iostream>
using namespace std;
template<class T2> class C2;
template<class T1>
class C1 {
friend C2<int>;
template<class T3> friend class C3;
friend T1;
friend class C4;
private:
int id;
};
template<class T2>
class C2 {
public:
void func1() {
C1<double>c1;
c1.id = 123;
cout << c1.id << endl;
}
};
template<class T3>
class C3 {
public:
void func1() {
C1<double>c1;
c1.id = 456;
cout << c1.id << endl;
}
};
class C4 {
public:
void func1() {
C1<C4>c1;
c1.id = 789;
cout << c1.id << endl;
}
void func2() {
C1<int>c1;
c1.id = 321;
cout << c1.id << endl;
}
};
int main() {
C2<int>c2;
c2.func1();
C3<int>c3Int;
c3Int.func1();
C3<double>c3Double;
c3Double.func1();
C4 c4;
c4.func1();
c4.func2();
return 0;
}
输出:
text
123
456
456
789
321
14. 函数模板作类模板友元
cpp
#include <iostream>
using namespace std;
template<class CT>
class C1 {
template<class T1, class T2> friend void func1();
template<class T3, class T4> friend void func2(T3, T4);
friend void func3(C1<CT>& c1) {
c1.id = 789;
cout << c1.id << endl;
}
private:
int id;
};
template<class T1, class T2>
void func1() {
C1<int>c1;
c1.id = 123;
cout << c1.id << endl;
}
template<class T3, class T4>
void func2(T3 a, T4 b) {
C1<int>c1;
c1.id = 456;
cout << c1.id << endl;
}
int main() {
func1<int, double>();
func1<int, int>();
func2(1, 2);
func2(1, 2.2);
cout << endl;
C1<int>c1;
func3(c1);
C1<double>c11;
func3(c11);
return 0;
}
输出:
text
123
123
456
456
789
789
15. 可变参函数模板的基本用法
A.
cpp
#include <iostream>
using namespace std;
template<class T1, class T2>
void func1(T1 a, T2 b) {
cout << a << "--" << b << endl;
}
void func3() {
cout << "这里结束递归" << endl;
}
template<class T33, class ... T3>
void func3(T33 b, T3 ...a) {
cout << "剩余参数个数:" << sizeof...(T3) << "--" << sizeof...(a) << endl;
cout << b << endl;
func3(a...);
}
int main() {
func1(1, 2);
func3(1, 2, 3, 4);
func3();
func3(1);
func3(1,2);
func3(1,2.2,"3.3");
func3(1,2.2,"3.3", nullptr);
return 0;
}
输出:
text
1--2
剩余参数个数:3--3
1
剩余参数个数:2--2
2
剩余参数个数:1--1
3
剩余参数个数:0--0
4
这里结束递归
这里结束递归
剩余参数个数:0--0
1
这里结束递归
剩余参数个数:1--1
1
剩余参数个数:0--0
2
这里结束递归
剩余参数个数:2--2
1
剩余参数个数:1--1
2.2
剩余参数个数:0--0
3.3
这里结束递归
剩余参数个数:3--3
1
剩余参数个数:2--2
2.2
剩余参数个数:1--1
3.3
剩余参数个数:0--0
nullptr
这里结束递归
B.
cpp
#include <iostream>
using namespace std;
template<class T1, class T2>
void func1(T1 a, T2 b) {
cout << a << "--" << b << endl;
}
template<class T33, class ... T3>
void func3(T33 b, T3 ...a) {
cout << "剩余参数个数:" << sizeof...(T3) << "--" << sizeof...(a) << endl;
cout << b << endl;
if constexpr (sizeof...(a) > 0) {
func3(a...);
}
}
int main() {
func1(1, 2);
func3(1, 2, 3, 4);
return 0;
}
输出:
text
1--2
剩余参数个数:3--3
1
剩余参数个数:2--2
2
剩余参数个数:1--1
3
剩余参数个数:0--0
4
16. 可变参函数模板-折叠表达式
cpp
#include <iostream>
using namespace std;
template<class ...T1>
void func1(T1 ...a) {
int sum = 0;
for (auto val : { a... }) {
cout << val << endl;
sum += val;
}
cout << sum << endl;
}
int sum2 = 0;
template<class T2, class ...T3>
void func3(T2 a, T3 ...b) {
sum2 += a;
if constexpr (sizeof...(b) > 0) {
func3(b...);
}
else {
cout << sum2 << endl;
}
}
template<class ...T4>
void func4(T4 ...a) {
cout << (... - a) << endl;
cout << (a - ...) << endl;
(cout << ... << a);
cout << endl;
}
template<class ...T5>
void func5(T5 ... a) {
cout << (10 - ... - a) << endl;
cout << (a - ... - 10) << endl;
}
int main() {
func4(1, 2, 3, 4);
func5(1, 2, 3, 4);
func1(1, 2, 3, 4);
func3(1, 2, 3, 4);
return 0;
}
输出:
text
-8
-2
1234
0
8
1
2
3
4
10
10
17. 可变参表达式
cpp
#include <iostream>
using namespace std;
template<class ...T2>
void func2(T2 ...a) {
cout << (... + a) << endl;
}
template<class ...T1>
void func1(T1 ...a) {
cout << (... + a) << endl;
func2(2 * a...);
func2(1 + a...);
}
int main() {
func1(1, 2, 3, 4);
return 0;
}
输出:
text
10
20
14
18. 可变参类模板的递归继承
cpp
#include <iostream>
using namespace std;
template<class ...T1>
class C1 {
public:
C1() {
printf("C1--T1\n");
}
};
template<class T2, class ...T3>
class C1<T2, T3...> : private C1<T3...> {
public:
C1() {
printf("C1--T2--T3--%s--%d\n", typeid(T2).name(), sizeof...(T3));
}
};
int main() {
C1<int, double, float>c1;
return 0;
}
输出:
text
C1--T1
C1--T2--T3--float--0
C1--T2--T3--double--1
C1--T2--T3--int--2
19. 可变参类模板的递归组合
cpp
#include <iostream>
using namespace std;
template<class ...T1>
class C1 {
public:
C1() {
printf("C1--T1--组合\n");
}
};
template<class T2, class ...T3>
class C1<T2, T3...> {
public:
C1() {
printf("C1--T2--T3--%s--%d\n", typeid(T2).name(), sizeof...(T3));
}
C1<T3...>c1;
};
int main() {
C1<int, double, float>c1;
return 0;
}
输出:
text
C1--T1--组合
C1--T2--T3--float--0
C1--T2--T3--double--1
C1--T2--T3--int--2
20. 模板中的多态
cpp
#include <iostream>
using namespace std;
class Father {
public:
virtual void say() {}
virtual ~Father() {}
};
class Son1 : public Father {
public:
virtual void say() {
cout << "son1" << endl;
}
};
class Son2 : public Father {
public:
virtual void say() {
cout << "son2" << endl;
}
};
class Son3 {
public:
void say() {
cout << "son3" << endl;
}
};
class Son4 {
public:
void say() {
cout << "son4" << endl;
}
};
template<class T1>
void func1(T1& son) {
son.say();
}
int main() {
Son1 son1;
Father *fa1=&son1;
Father *fa2=new Son2;
fa1->say();
fa2->say();
Son1 son11;
Son2 son21;
Father &fa11=son11;
Father &fa21=son21;
fa11.say();
fa21.say();
Son3 son3;
Son4 son4;
func1(son3);
func1(son4);
return 0;
}
输出:
text
son1
son2
son1
son2
son3
son4
21. 子类作父类的模板参数
cpp
#include <iostream>
using namespace std;
template<class T1>
class Father {
public:
void sonSay() {
T1& son = static_cast<T1&>(*this);
son.say();
}
};
class Son1 : public Father<Son1> {
public:
void say() {
cout << "son1" << endl;
}
};
template<class T2>
class Son2 : public Father<Son2<T2>> {
public:
void say() {
cout << "son2" << endl;
}
};
int main() {
Son1 son1;
son1.sonSay();
Son2<int> son2;
son2.sonSay();
return 0;
}
输出:
text
son1
son2
22. 类模板中的混入
cpp
#include <iostream>
using namespace std;
class A {
public:
A() {
cout << "a" << endl;
}
int a;
};
class B {
public:
B() {
cout << "b" << endl;
}
int b;
};
class C : public A {
};
class D : public A, public B {
};
template<class ...T1>
class E : public T1...{
public:
E() { cout << "e" << endl; }
};
template<class ...T2>
class F : public E<T2...> {
public:
F() { cout << "f" << endl; }
};
using EA = E<A>;
using FEAB = F<A, B>;
int main() {
EA ea;
ea.a = 123;
cout << ea.a << endl;
FEAB feab;
feab.a = 123;
feab.b = 456;
cout << feab.a << "--" << feab.b << endl;
E<A>e1;
e1.a = 123;
cout << e1.a << endl;
E<A, B>e2;
e2.a = 123;
e2.b = 456;
cout << e2.a << "--" << e2.b << endl;
F<A>f1;
f1.a = 123;
cout << f1.a << endl;
C c1;
c1.a = 123;
cout << c1.a << endl;
D d1;
d1.a = 123;
d1.b = 456;
cout << d1.a << "--" << d1.b << endl;
return 0;
}
输出:
text
a
e
123
a
b
e
f
123--456
a
e
123
a
b
e
123--456
a
e
f
123
a
123
a
b
123--456
23. 左值和右值
cpp
#include <iostream>
using namespace std;
void func1() {
int a;
a = 123;
int b = 456;
a = a + 1;
b = b + 2;
int c = a + b;
int d = 123456;
}
int main() {
func1();
return 0;
}
24. 左值引用和右值引用
A.
cpp
#include <iostream>
#include<string>
using namespace std;
void func1() {
int a = 123;
int& b = a;
b = 456;
cout << a << " " << b << endl;
const int& e = a;
const int& f = 123;
cout << f << endl;
const string& g = string{ "abc" };
cout << g << endl;
const int& i = a + 1;
}
void func2() {
int a = 123;
int&& c = 123;
c = 456;
cout << c << endl;
string&& d = string{ "abc" };
d = "xyz";
cout << d << endl;
const int&& e = 123;
const string&& f = string{ "abc" };
int&& h = a + 1;
cout << h << endl;
const int&& i = a + 1;
}
void func3() {
int a;
a = 123;
int* p = nullptr;
int&& e = NULL;
cout << e << endl;
}
int main() {
func1();
func2();
func3();
return 0;
}
输出:
text
456 456
123
abc
456
xyz
124
0
B.
cpp
#include <iostream>
#include<string>
using namespace std;
void func1() {
int i = 123;
int& b = ++i;
printf("%d-%d--%p-%p\n", i, b, &i, &b);
(++i) = 456;
printf("%d-%d--%p-%p\n", i, b, &i, &b);
int&& c = i++;
printf("%d-%d--%p-%p\n", i, c, &i, &c);
}
void func2() {
int a = 123;
int& b = a;
int& c = b;
int&& e = 456;
int& f = e;
}
void func4(int a, int& b, int&& c) {
}
void func5() {
int a = 123;
int& b = a;
int&& c = std::move(a);
printf("%d-%d-%d---%p-%p-%p\n", a, b, c, &a, &b, &c);
c = 456;
printf("%d-%d-%d---%p-%p-%p\n", a, b, c, &a, &b, &c);
int&& d = 789;
int&& e = std::move(d);
printf("%d-%d---%p-%p\n", d, e, &d, &e);
e = 123;
printf("%d-%d---%p-%p\n", d, e, &d, &e);
int f = a;
int g = std::move(a);
printf("%d-%d-%d---%p-%p-%p\n", a, f, g, &a, &f, &g);
string h = "abc";
string i = h;
string gg = std::move(h);
std::move(h);
printf("%s-%s-%s===%p-%p-%p\n", h.c_str(), i.c_str(), gg.c_str(), &h, &i, &gg);
}
int main() {
int x = 123;
func1();
func2();
func4(x, x, 123);
func5();
return 0;
}
输出:
text
124-124--00000057B74FF434-00000057B74FF434
456-456--00000057B74FF434-00000057B74FF434
457-456--00000057B74FF434-00000057B74FF494
123-123-123---00000057B74FF2D4-00000057B74FF2D4-00000057B74FF2D4
456-456-456---00000057B74FF2D4-00000057B74FF2D4-00000057B74FF2D4
789-789---00000057B74FF354-00000057B74FF354
123-123---00000057B74FF354-00000057B74FF354
456-456-456---00000057B74FF2D4-00000057B74FF394-00000057B74FF3B4
-abc-abc===00000057B74FF3D8-00000057B74FF418-00000057B74FF458
25. 万能引用
cpp
#include <iostream>
#include<string>
using namespace std;
template<class T1>
void func1(T1& a) {
cout << a << endl;
}
template<class T2>
void func2(T2&& a) {
cout << a << endl;
a = 456;
}
template<class T3>
class C1 {
public:
void func1(T3&& a) {
cout << a << endl;
}
template<class T4>
void func2(T4&& a) {
cout << a << endl;
}
};
template<class T5>
void func3(const T5&& a) {
cout << a << endl;
}
int main() {
int a = 123;
func1(a);
func2(a);
func2(123);
cout << a << endl;
C1<int>c1;
c1.func1(123);
c1.func2(a);
func3(123);
auto&& x = 123;
auto&& y = x;
return 0;
}
输出:
text
123
123
123
456
123
456
123
26. 完美转发
A.
cpp
#include <iostream>
#include<string>
using namespace std;
void func2(int& a, int&& b) {
cout << a << "--" << b << endl;
}
template<class T1, class T2>
void func1(T1&& a, T2&& b) {
func2(
std::forward<T1>(a),
std::forward<T2>(b)
);
}
void func3(int& a) {
cout << "左值引用" << endl;
}
void func3(const int& a) {
cout << "const 左值引用" << endl;
}
void func3(int&& a) {
cout << "右值引用" << endl;
}
template<class T3>
void func4(T3&& a) {
func3(
std::forward<T3>(a)
);
}
int main() {
int a = 1;
func1(a, 123);
int&& b = 123;
int& c = b;
int i = 1;
const int j = 2;
int& k = i;
int&& l = 3;
const int& m = i;
const int&& n = 3;
func4(i);
func4(123);
func4(std::move(i));
func4(int(123));
func4(j);
func4(k);
func4(l);
func4(m);
func4(n);
return 0;
}
输出:
text
1--123
左值引用
右值引用
右值引用
右值引用
const 左值引用
左值引用
左值引用
const 左值引用
const 左值引用
B.
cpp
#include <iostream>
#include<string>
using namespace std;
int func2(int& a, int&& b) {
cout << "func2--" << a << "--" << b << endl;
return a + b;
}
string func3(int& a, int&& b, string c) {
cout << "func3--" << a << "--" << b << "--" << c << endl;
return c;
}
template<class F, class ...T>
decltype(auto) func1(F f, T && ...a) {
return f(
std::forward<T>(a)...
);
}
int main() {
int a = 123;
int rs1 = func1(func2, a, 123);
string rs2 = func1(func3, a, 123, "abc");
cout << endl << endl;
cout << rs1 << "--" << rs2 << endl;
return 0;
}
输出:
text
func2--123--123
func3--123--123--abc
246--abc
27. 替换失败不是错误
cpp
#include <iostream>
#include<string>
#include<vector>
using namespace std;
template<class T>
typename T::size_type func1(T a) {
return 123;
}
int func1(int a){
return 456;
}
int main() {
int a = 1;
cout << func1(a) << endl;
cout << func1(vector<int>{a}) << endl;
return 0;
}
输出:
text
456
123
28. std::enable_if
A.
cpp
#include <iostream>
#include<string>
using namespace std;
template<class T>
struct S1 {
typedef T type;
};
template<class T1>
std::enable_if_t<(sizeof(T1) > 2), T1> func1(T1 a) {
return a;
}
int main() {
int a = func1(1);
cout << a << endl;
double b = 123;
double c = func1(b);
cout << c << endl;
enable_if<true>::type* p1 = nullptr;
enable_if<true, int>::type a1 = 123;
enable_if<(1 < 2)>::type* p2 = nullptr;
S1<int>::type a111 = 123;
cout << a111 << endl;
S1<string>::type b111 = "abc";
cout << b111 << endl;
return 0;
}
输出:
text
1
123
123
abc
B.
cpp
#include <iostream>
#include<string>
using namespace std;
class C1 {
public:
template<
class T1,
class T2 = std::enable_if_t<std::is_convertible<T1, string>::value>
>
C1(T1&& name) {
this->name = std::forward<T1>(name);
cout << "构造函数模板" << endl;
}
C1(const C1& c1) {
this->name = c1.name;
cout << "拷贝构造函数" << endl;
}
string name;
};
int main() {
string name = "tom";
C1 c1(name);
C1 c2(c1);
bool rs = std::is_convertible<double, int>::value;
cout << (rs == true) << endl;
return 0;
}
输出:
text
构造函数模板
拷贝构造函数
1
29. std-conditional
cpp
#include <iostream>
#include<string>
using namespace std;
int main() {
conditional<true, int, char>::type t1;
conditional<false, int, char>::type t2;
cout << typeid(t1).name() << endl;
cout << typeid(t2).name() << endl;
constexpr int a = 23;
conditional<
(a > 100),
conditional<(a > 150), int, char>::type,
conditional<(a > 50), bool, double>::type
>::type t3;
cout << typeid(t3).name() << endl;
return 0;
}
输出:
text
int
char
double
30. std-remove_all_extents
cpp
#include <iostream>
#include<string>
#include<vector>
using namespace std;
template <class _Tp>
struct remove_all_extents_x {
typedef _Tp type;
};
template <class _Tp>
struct remove_all_extents_x<_Tp[]> {
typedef typename remove_all_extents_x<_Tp>::type type;
};
template <class _Tp, size_t _Np>
struct remove_all_extents_x<_Tp[_Np]> {
typedef typename remove_all_extents_x<_Tp>::type type;
};
int main() {
int a1[2][3][4]{};
remove_all_extents_x<int[2][3][4]>::type t11;
extern int b1[];
cout << typeid(t11).name() << endl;
int a[2]{};
int b[2][3]{};
int c[2][3][4]{};
char d[2][3]{};
int* e[2][3]{};
vector<int>f[2]{};
std::remove_all_extents<decltype(d)>::type t1;
std::remove_all_extents<decltype(e)>::type t2;
std::remove_all_extents<decltype(f)>::type t3;
cout << typeid(t1).name() << endl;
cout << typeid(t2).name() << endl;
cout << typeid(t3).name() << endl;
return 0;
}
输出:
text
int
char
int * __ptr64
class std::vector<int,class std::allocator<int> >
31. 萃取-基本概念
cpp
#include <iostream>
#include<string>
using namespace std;
int main(){
return 0;
}
32. 萃取-固定萃取
A.
cpp
#include <iostream>
#include<string>
using namespace std;
template<class T1, class T2>
T1 func1(const T2* start, const T2* end) {
cout << typeid(T1).name() << endl;
cout << typeid(T2).name() << endl;
T1 sum{};
for (;;) {
sum += (*start);
if (start == end) {
break;
}
start++;
}
return sum;
}
template<class T1>
struct sumType {};
template<>
struct sumType<char> {
using type = int;
};
template<>
struct sumType<int> {
using type = int64_t;
};
template<class T1>
auto func2(const T1* start, const T1* end) {
using sumT = typename sumType<T1>::type;
sumT sum{};
for (;;) {
sum += (*start);
if (start == end) {
break;
}
start++;
}
return sum;
}
int main() {
int a[] = { 1,2,3 };
int b[] = { 1000000000,2000000000,2000000000 };
char c[] = "abc";
cout << func1<int>(&a[0], &a[2]) << endl;
cout << func1<int64_t>(&b[0], &b[2]) << endl;
cout << func1<int>(&c[0], &c[2]) << endl;
cout << endl;
cout << func2(&a[0], &a[2]) << endl;
cout << func2(&b[0], &b[2]) << endl;
cout << func2(&c[0], &c[2]) << endl;
return 0;
}
输出:
text
int
int
6
__int64
int
5000000000
int
char
294
6
5000000000
294
B.
cpp
#include <iostream>
#include<string>
#include<vector>
#include<list>
#include<array>
using namespace std;
template<class T1>
struct getType {
using type = typename T1::value_type;
};
template<class T1, size_t size>
struct getType<array<T1, size>> {
using type = T1;
};
template<class T1>
using TYPE = typename getType<T1>::type;
template<class T1>
void func1(const T1& a) {
cout << typeid(TYPE<T1>).name() << endl;
}
int main() {
vector<int>a{};
list<double>b{};
array<char, 10>c{};
func1(a);
func1(b);
func1(c);
getType<decltype(a)>::type t1;
getType<decltype(b)>::type t2;
getType<decltype(c)>::type t3;
TYPE<decltype(a)> t11;
TYPE<decltype(b)> t21;
TYPE<decltype(c)> t31;
cout << typeid(t11).name() << endl;
cout << typeid(t21).name() << endl;
cout << typeid(t31).name() << endl;
int a1[2]{};
vector<int>b1{};
remove_all_extents<decltype(a1)>::type t111;
remove_all_extents<decltype(b1)>::type t211;
cout << typeid(t111).name() << endl;
cout << typeid(t211).name() << endl;
return 0;
}
输出:
text
int
double
char
int
double
char
int
class std::vector<int,class std::allocator<int> >
32. 萃取-退化功能的实现
A.
cpp
#include <iostream>
#include<string>
using namespace std;
template <class T1>
struct clearConst {
using type = T1;
};
template <class T1>
struct clearConst<const T1> {
using type = T1;
};
template <class T1>
struct clearReference {
using type = T1;
};
template <class T1>
struct clearReference<T1&> {
using type = T1;
};
template <class T1>
struct clearReference<T1&&> {
using type = T1;
};
int main() {
int a = 123;
const int b = 456;
int& c = a;
int&& d = 789;
const int& e = b;
cout << is_same<clearConst<decltype(b)>::type, int>::value << endl;
cout << is_same<clearReference<decltype(c)>::type, int>::value << endl;
cout << is_same<clearReference<decltype(d)>::type, int>::value << endl;
cout << endl;
cout << is_same<clearConst<clearReference<decltype(e)>::type>::type, int>::value << endl;
cout<<is_same<clearReference<clearConst<decltype(e)>::type>::type ,int>::value<<endl;
const int b1=456;
std::decay<decltype(b1)>::type t1;
cout<<is_same<decay<const int&&>::type ,int>::value<<endl;
return 0;
}
输出:
text
1
1
1
1
0
1
B.
cpp
#include <iostream>
#include<string>
using namespace std;
template <class T1>
struct clearConst {
using type = T1;
};
template <class T1>
struct clearConst<const T1> {
using type = T1;
};
template <class T1>
struct clearReference {
using type = T1;
};
template <class T1>
struct clearReference<T1&> {
using type = T1;
};
template <class T1>
struct clearReference<T1&&> {
using type = T1;
};
template <class T1>
struct myDecay : clearReference<clearConst<T1>>::type {
};
template <class T1, size_t size>
struct myDecay<T1[size]> {
using type = T1*;
};
template <class T1>
struct myDecay<T1[]> {
using type = T1*;
};
template <class T1, class...args>
struct myDecay<T1(args...)> {
using type = T1(*)(args...);
};
int func1(int a, char b) {
cout << "func1--" << a << "---" << b << endl;
return 0;
}
int main() {
int a = 123;
const int b = 456;
int& c = a;
int&& d = 789;
const int&& e = 123;
int f[4]{};
const int g[5]{};
cout << typeid(decltype(d)).name() << endl;
cout << typeid(decay<decltype(d)>::type).name() << endl;
cout << typeid(myDecay<decltype(d)>::type).name() << endl;
cout << "----------------" << endl;
cout << typeid(decltype(e)).name() << endl;
cout << typeid(decay<decltype(e)>::type).name() << endl;
cout << typeid(myDecay<decltype(e)>::type).name() << endl;
cout << "----------------" << endl;
cout << typeid(decltype(g)).name() << endl;
cout << typeid(decay<decltype(g)>::type).name() << endl;
cout << typeid(myDecay<decltype(g)>::type).name() << endl;
cout << "----------------" << endl;
cout << typeid(decltype(func1)).name() << endl;
cout << typeid(decay<decltype(func1)>::type).name() << endl;
cout << typeid(myDecay<decltype(func1)>::type).name() << endl;
return 0;
}
输出:
text
int
int
int
----------------
int
int
int
----------------
int const [5]
int const * __ptr64
int const * __ptr64
----------------
int __cdecl(int,char)
int (__cdecl*)(int,char)
int (__cdecl*)(int,char)
33. 萃取-值萃取
cpp
#include <iostream>
#include<string>
using namespace std;
class C1 {
public:
C1(int a, int b) {
this->a = a;
this->b = b;
}
int a;
int b;
C1& operator+=(const C1& c1) {
this->a += c1.a;
this->b += c1.b;
return *this;
}
};
template<class T1>
struct sumType {};
template<>
struct sumType<char> {
using type = int;
static type initSum() {
return 0;
}
};
template<>
struct sumType<int> {
using type = int64_t;
static type initSum() {
return 0;
}
};
template<>
struct sumType<C1> {
using type = C1;
static type initSum() {
return C1(0, 0);
}
};
template<class T1>
auto func2(const T1* start, const T1* end) {
using sumT = typename sumType<T1>::type;
sumT sum = sumType<T1>::initSum();
for (;;) {
sum += (*start);
if (start == end) {
break;
}
start++;
}
return sum;
}
int main() {
int a[] = { 1,2,3 };
int b[] = { 1000000000,2000000000,2000000000 };
char c[] = "abc";
C1 d[]{ C1(1,11),C1(2,22),C1(3,33) };
cout << func2(&a[0], &a[2]) << endl;
cout << func2(&b[0], &b[2]) << endl;
cout << func2(&c[0], &c[2]) << endl;
C1 rs = func2(&d[0], &d[2]);
cout << rs.a << "--" << rs.b << endl;
return 0;
}
输出:
text
6
5000000000
294
6--66
34. 萃取-类型萃取
cpp
#include <iostream>
#include<string>
using namespace std;
template<class T1, class T2>
struct myIsSame {
using type = bool;
static const type value = false;
};
template<class T1>
struct myIsSame<T1, T1> {
using type = bool;
static const type value = true;
};
int main() {
int a = 123;
int b = 456;
double c = 7.89;
const int e = 789;
cout << is_same<decltype(a), decltype(b)>::value << endl;
cout << is_same<decltype(a), decltype(c)>::value << endl;
cout << endl;
cout << myIsSame<decltype(a), decltype(b)>::value << endl;
cout << myIsSame<decltype(a), decltype(c)>::value << endl;
cout<<is_const<decltype(a)>::value<<endl;
cout<<is_const<decltype(e)>::value<<endl;
return 0;
}
输出:
text
1
0
1
0
0
1
35. 萃取-策略萃取
cpp
#include <iostream>
#include<string>
using namespace std;
class C1 {
public:
C1(int a, int b) {
this->a = a;
this->b = b;
}
int a;
int b;
C1& operator+=(const C1& c1) {
this->a += c1.a;
this->b += c1.b;
return *this;
}
C1& operator-=(const C1& c1) {
this->a -= c1.a;
this->b -= c1.b;
return *this;
}
};
template<class T1>
struct sumType {};
template<>
struct sumType<char> {
using type = int;
static type initSum() {
return 0;
}
};
template<>
struct sumType<int> {
using type = int64_t;
static type initSum() {
return 0;
}
};
template<>
struct sumType<C1> {
using type = C1;
static type initSum() {
return C1(0, 0);
}
};
struct myAdd {
template<class T1, class T2>
static void algorithm(T1& sum, const T2& val) {
sum += val;
}
};
struct mySub {
template<class T1, class T2>
static void algorithm(T1& sum, const T2& val) {
sum -= val;
}
};
template<class T1, class T2 = myAdd>
auto func2(const T1* start, const T1* end) {
using sumT = typename sumType<T1>::type;
sumT sum = sumType<T1>::initSum();
for (;;) {
T2::algorithm(sum, *start);
if (start == end) {
break;
}
start++;
}
return sum;
}
int main() {
int a[] = { 1,2,3 };
int b[] = { 1000000000,2000000000,2000000000 };
char c[] = "abc";
C1 d[]{ C1(1,11),C1(2,22),C1(3,33) };
cout << func2<int, mySub>(&a[0], &a[2]) << endl;
cout << func2(&b[0], &b[2]) << endl;
cout << func2(&c[0], &c[2]) << endl;
C1 rs = func2<C1, mySub>(&d[0], &d[2]);
cout << rs.a << "===" << rs.b << endl;
return 0;
}
输出:
text
-6
5000000000
294
-6===-66
36. 元编程-原函数
A.
cpp
#include <iostream>
#include<string>
using namespace std;
int func1(int a, int b) {
return a + b;
}
constexpr int func2(int a, int b) {
return a + b;
}
template<class T1>
constexpr T1 func3(T1 a, T1 b) {
return a + b;
}
int main() {
int a = func1(1111, 2222);
constexpr int b = func2(11111, 22222);
constexpr int c = func3(111, 222);
cout << a << "--" << b << endl;
return 0;
}
输出:
text
3333--33333
B.
cpp
#include <iostream>
#include<string>
using namespace std;
template<int a>
constexpr int func1() {
return a * func1<a - 1>();
}
template<>
constexpr int func1<0>() {
return 1;
}
template<int ...a>
constexpr int func2 = 0;
template<int first, int ...a>
constexpr int func2<first, a...> = first + func2<a...>;
int main() {
constexpr int a = func1<10>();
cout << a << endl;
constexpr int b = func2<1, 2, 3, 4, 5, 6, 7, 8, 9, 10>;
cout << b << endl;
static_assert(b == 55, "b error");
return 0;
}
输出:
text
3628800
55
参考资料
c++泛型编程与模板
原文地址:C++模板从入门到入土