This commit is contained in:
Light-City
2020-03-03 09:34:21 +08:00
parent 60af6600e4
commit 50058c3ec2
31 changed files with 185 additions and 178 deletions

View File

@@ -0,0 +1,66 @@
//
// Created by light on 19-11-2.
//
// variadic template(c++11) 数量不定的模板参数
#include <iostream>
#include <vector>
#include <tuple>
using namespace std;
// 参数个数 参数个数逐一递减
// 参数类型 参数类型也逐一递减
// (3)
// 需要重载一个终止函数
template<typename T>
void _hash(size_t &seed, const T &val) {
cout << "hash over " << val << endl;
}
// (2)
// 展开函数, 把参数分为一个普通参数和一个参数包,调用一次,参数包大小就减一
template<typename T,typename... Args>
void _hash(size_t &seed, const T& val,const Args &... args) {
cout << "parameter " << val<< endl;
// 递归调用自己
_hash(seed, args...); // 上面如果不给T参数,会自己调用自己成死循环
}
// 泛化版 (1)
template<typename ...Args>
size_t _hash(const Args &... args) {
cout << "hash start " << endl;
size_t seed = 10;
// 递归调用自己
_hash(seed, args...);
return seed;
}
template<typename ...Args>
class A {
private:
int size = 0; // c++11 支持类内初始化
public:
A() {
size = sizeof...(Args);
cout << size << endl;
}
};
int main(void) {
size_t f = 10;
_hash("asdas", 2, 3, 4);
A<int, string, vector<int>> a; // 类型任意
// Tuple就是利用这个特性(变长参数模板)
tuple<int, string> t = make_tuple(1, "hha");
int firstArg = get<0>(t);
string secondArg = get<1>(t);
cout << firstArg << " " << secondArg << endl;
return 0;
}

View File

@@ -0,0 +1,32 @@
//
// Created by light on 19-11-4.
//
#include <iostream>
#include <bitset>
using namespace std;
// example 1
void printX() {
}
// 特化
template<typename T, typename... Type>
void printX(const T &firstArg, const Type &...args) {
cout << firstArg << endl; // 先减少一个做操作
printX(args...); // 其余的继续分为一个+一包进行递归知道没有了 调用printX()
}
// 如果写了下面接收任意参数,下面这个跟上面可以共存 泛化版 永远不会被调用,前面特化把它取代了
template<typename T, typename... Type>
void printX(const Type &...args) {
printX(args...);
}
int main() {
printX(1, "hello", bitset<16>(377), 42);
return 0;
}

View File

@@ -0,0 +1,34 @@
//
// Created by light on 19-11-4.
//
#include <iostream>
using namespace std;
void print(const char *s) {
while (*s) {
if (*s == '%' && *(++s) != '%')
throw std::runtime_error("invalid format string: missing arguments");
std::cout << *s++;
}
}
template<typename T, typename... Args>
void print(const char *s, T value, Args... args) {
while (*s) {
if (*s == '%' && *(++s) != '%') {
std::cout << value;
print(++s, args...); // 即便当 *s == 0 也会产生调用,以检测更多的类型参数。
return;
}
std::cout << *s++;
}
throw std::logic_error("extra arguments provided to printf");
}
int main() {
int *pi = new int;
print("%d %s %p %f\n", 15, "Acc", pi, 3.14);
return 0;
}

View File

@@ -0,0 +1,31 @@
//
// Created by light on 19-11-4.
//
#include <iostream>
using namespace std;
// 参数type相同的max
int max(initializer_list<int> initializerList) {
int res = *initializerList.begin();
for (auto elem:initializerList)
res = max(res, elem);
return res;
}
// 参数type相同的maximum
int maximum(int n) {
return n;
}
template<typename ...Args>
int maximum(int n, Args...args) {
return std::max(n, maximum(args...));
}
int main() {
cout << max({10, 8, 100, 1}) << endl;
cout << maximum(57, 48, 60, 100, 20, 18) << endl;
}

View File

@@ -0,0 +1,44 @@
//
// Created by light on 19-11-4.
//
#include <iostream>
#include <tuple>
#include <bitset>
using namespace std;
// tuple递归调用
// 得出这种打印[7,5....,42]
// 需要知道有几个以及现在操作的是第几个 sizeof...()
// cout<< make_tuple(7.5,string("hello"),bitset<16>(377),47);
template<int IDX, int MAX, typename... Args>
struct print_tuple {
static void print(ostream &os, const tuple<Args...> &t) {
os << get<IDX>(t) << (IDX + 1 == MAX ? "" : ",");
print_tuple<IDX + 1, MAX, Args...>::print(os, t);
}
};
// 偏特化
template<int MAX, typename... Args>
struct print_tuple<MAX, MAX, Args...> {
static void print(ostream &os, const tuple<Args...> &t) {
}
};
template<typename ... Args>
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
os << "[";
print_tuple<0, sizeof...(Args), Args...>::print(os, t);
return os << "]";
}
int main() {
cout << make_tuple(7.5, string("hello"), bitset<16>(377), 47) << endl;
}

View File

@@ -0,0 +1,52 @@
//
// Created by light on 19-11-4.
//
#include <iostream>
using namespace std;
// 上一个例子:variadic5.cpp为递归调用
// 当前这个例子为递归继承
namespace light {
template<typename...Values>
class tuple;
template<>
class tuple<> {
};
template<typename Head, typename...Tail>
class tuple<Head, Tail...> : private tuple<Tail...> {
typedef tuple<Tail...> inherited;
protected:
Head m_head;
public:
tuple() {}
tuple(Head h, Tail...tail) : m_head(h), inherited(tail...) {}
// decltype()中的m_head必须放到前面,否则编译器找不到
auto head() -> decltype(m_head) { return m_head; }
// 或者 Head head() { return m_head; }
inherited &tail() { return *this; }
};
}
/**
* string 32 8字节对齐
* float 4
* int 4
* 4+4+32=40 自底向上
*/
int main() {
using light::tuple;
tuple<int, float, string> t(41, 6.3, "nico");
cout << sizeof(t) << endl;
cout << t.head() << endl;
cout << t.tail().head() << endl;
cout << t.tail().tail().head() << endl;
return 0;
}

View File

@@ -0,0 +1,57 @@
//
// Created by light on 19-11-4.
//
#include <iostream>
using namespace std;
namespace light {
template<typename...Values>
class tuple;
template<>
class tuple<> {
};
template<typename Head, typename...Tail>
class tuple<Head, Tail...> {
typedef tuple<Tail...> composited;
protected:
Head m_head;
composited m_tai;
public:
tuple() {}
int get() { return sizeof(composited);}
tuple(Head h, Tail...tail) : m_head(h), m_tai(tail...) {}
// decltype()中的m_head必须放到前面,否则编译器找不到
auto head() -> decltype(m_head) { return m_head; }
// 或者 Head head() { return m_head; }
composited &tail() { return m_tai; }
};
}
// 根据string为8字节对齐,我们得出8字节对齐
// 第一次 int 4字节Head调整到边界8 那composite呢?继续往下分析
// 第二次 把第一次的composited拆分为float与一包, float也占4字节,调整到8边界为8字节,那这一步的composited呢?继续往下分析
// 第三次 把第二次的compoisted拆分成sting与一包, string占32字节,已经为8倍数,无需调整,而这一步的composited呢?由于到这里一包已经没了,就会调用它的全特化版本,全特环版本为空,sizeof为1,
// 调整到8的倍数为8.
// 因此最后的内存结构(自底向上)为8 + 8 + 32 + 8 = 56 64位机器结果
struct A {
string a;
float b;
};
int main() {
using light::tuple;
tuple<int, float, string> t(41, 6.3, "nico");
cout<<sizeof(A)<<endl;
cout<<t.get()<<endl;
cout << sizeof(t) << endl;
cout << t.head() << endl;
cout << t.tail().head() << endl;
cout << t.tail().tail().head() << endl;
return 0;
}