最值得推荐的100本计算机书籍

Book-100 最值得推荐的100本计算机书籍 参与贡献: 纯洁的微笑 ufan0 汤圆 aracwong 轩辕御龙 参与贡献 感兴趣一起深度参与此开源项目的朋友,加我微信 puresmilea 目录 书名 豆瓣评分 投票人数 类别 《Effective Java中文版》(第三版) 9.9 105 Java 《C程序设计语言》 9.4 4471 C 《代码大全(第2版)》 9.3 3802 算法 《Java编程思想》(第四版) 9.1 3724 Java 《JavaScript高级程序设计(第3版)》 9.3 2299 JavaScript 《Head First设计模式》 9.2 3031 基础 《鸟哥的Linux私房菜》(基础学习篇) 9.1 2988 Linux 《Python编程:从入门到实践》 9.1 2732 Python 《计算机程序的构造和解释(原书第2版)》 9.5 2309 基础 《JavaScript语言精粹》 9.1 1835 JavaScript 《程序员的自我修养》 8.8 2333 基础 《程序员修炼之道:从小工到专家》 8.6 2267 开发 《Unix环境高级编程》 9.4 2259 Unix 《Unix编程艺术》 9 2114 Unix 《编程珠玑(第二版)》 9....

August 25, 2022 · ityouknow

C++ SFINAE

考虑下面这个函数模板: template <typename T, typename U> void foo(T t, typename U::type u) { // ... } 到本节为止,我们所有的例子都保证了一旦咱们敲定了模板参数中 T 和 U,函数参变量 t 和 u 的类型都是成立的,比如下面这样: struct X { typedef float type; }; template <typename T, typename U> void foo(T t, typename U::type u) { // ... } void callFoo() { foo<int, X>(5, 5.0); // T == int, typename U::type == X::type == float } 那么这里有一个可能都不算是问题的问题 —— 对于下面的代码,你认为它会提示怎么样的错误: struct X { typedef float type; }; struct Y { typedef float type2; }; template <typename T, typename U> void foo(T t, typename U::type u) { // ....

August 17, 2022 · gyshgx868

偏特化与函数重载的比较

我们来先看一个函数重载的例子: void doWork(int); void doWork(float); void doWork(int, int); void f() { doWork(0); doWork(0.5f); doWork(0, 0); } 在这个例子中,我们展现了函数重载可以在两种条件下工作:参数数量相同、类型不同;参数数量不同。 仿照重载的形式,我们通过特化机制,试图实现一个模板的“重载”: template <typename T> struct DoWork; // (0) 这是原型 template <> struct DoWork<int> {}; // (1) 这是 int 类型的"重载" template <> struct DoWork<float> {}; // (2) 这是 float 类型的"重载" template <> struct DoWork<int, int> {}; // (3) 这是 int, int 类型的“重载” void f(){ DoWork<int> i; DoWork<float> f; DoWork<int, int> ii; } 这个例子在字面上“看起来”并没有什么问题,可惜编译器在编译的时候仍然提示出错了goo.gl/zI42Zv: 5 : error: too many template arguments for class template 'DoWork' template <> struct DoWork<int, int> {}; // 这是 int, int 类型的“重载” ^ ~~~~ 1 : note: template is declared here template <typename T> struct DoWork {}; // 这是原型 ~~~~~~~~~~~~~~~~~~~~~ ^ 从编译出错的失望中冷静一下,在仔细看看函数特化/偏特化和一般模板的不同之处:...

August 12, 2022 · gyshgx868

template不定长的模板参数

有没有一种办法能够让例子DoWork像重载一样,支持对长度不一的参数列表分别偏特化/特化呢? 答案当然是肯定的。 首先,首先我们要让模板实例化时的模板参数统一到相同形式上。逆向思维一下,虽然两个类型参数我们很难缩成一个参数,但是我们可以通过添加额外的参数,把一个扩展成两个呀。比如这样: DoWork<int, void> i; DoWork<float, void> f; DoWork<int, int > ii; 这时,我们就能写出统一的模板原型: template <typename T0, typename T1> struct DoWork; 继而偏特化/特化问题也解决了: template <> struct DoWork<int, void> {}; // (1) 这是 int 类型的特化 template <> struct DoWork<float, void> {}; // (2) 这是 float 类型的特化 template <> struct DoWork<int, int> {}; // (3) 这是 int, int 类型的特化 显而易见这个解决方案并不那么完美。首先,不管是偏特化还是用户实例化模板的时候,都需要多撰写好几个void,而且最长的那个参数越长,需要写的就越多;其次,如果我们的DoWork在程序维护的过程中新加入了一个参数列表更长的实例,那么最悲惨的事情就会发生 —— 原型、每一个偏特化、每一个实例化都要追加上void以凑齐新出现的实例所需要的参数数量。 所幸模板参数也有一个和函数参数相同的特性:默认实参(Default Arguments)。只需要一个例子,你们就能看明白了goo.gl/TtmcY9: template <typename T0, typename T1 = void> struct DoWork; template <typename T> struct DoWork<T> {}; template <> struct DoWork<int> {}; template <> struct DoWork<float> {}; template <> struct DoWork<int, int> {}; DoWork<int> i; DoWork<float> f; DoWork<double> d; DoWork<int, int> ii; 所有参数不足,即原型中参数T1没有指定的地方,都由T1自己的默认参数void补齐了。...

June 4, 2022 · gyshgx868

template根据类型执行代码

做出根据类型执行不同代码。要达成这一目的,模板并不是唯一的途径。比如之前我们所说的重载。如果把眼界放宽一些,虚函数也是根据类型执行代码的例子。此外,在C语言时代,也会有一些技法来达到这个目的,比如下面这个例子,我们需要对两个浮点做加法, 或者对两个整数做乘法: struct Variant { union { int x; float y; } data; uint32 typeId; }; Variant addFloatOrMulInt(Variant const* a, Variant const* b) { Variant ret; assert(a->typeId == b->typeId); if (a->typeId == TYPE_INT) { ret.x = a->x * b->x; } else { ret.y = a->y + b->y; } return ret; } 更常见的是 void*: #define BIN_OP(type, a, op, b, result) (*(type *)(result)) = (*(type const *)(a)) op (*(type const*)(b)) void doDiv(void* out, void const* data0, void const* data1, DATA_TYPE type) { if(type == TYPE_INT) { BIN_OP(int, data0, *, data1, out); } else { BIN_OP(float, data0, +, data1, out); } } 在C++中比如在 Boost....

April 25, 2022 · gyshgx868