exercies 1
考察 std::initializer_list <>
这份template函数参照简单的例子书写。这种方式会简单很多。
注意到我后面两次调用函数 average_list, 它的 std::initializer_list <>并不相同
#include<iostream>
#include<initializer_list>
#include<algorithm>double sum(std::initializer_list<double> i)
{double tot = 0;std::for_each(i.begin(), i.end(), [&tot](double db){tot += db;});return tot;
}template<typename T>
T average_list(const std::initializer_list<T> list)
{T temp = 0;std::for_each(list.begin(), list.end(), [&list,&temp](T value){temp += value;});return temp;
}int main()
{/*double result = sum({2.5,4.2,1.5});std::cout << result << "\n";*/auto q = average_list({ 2.5,4.2,1.5 });std::cout << q << "\n";std::cout << average_list({20, 30, 19, 17, 45, 38}) << "\n";auto p = average_list<double>({'A', 70, 65.33}); // u pass in a type explicitlystd::cout << p;return 0;
}
exercies 2
在简单的类成员函数的基础上添加了 move semantic,移动构造 和 移动赋值。
driver的驱动函数可以自己实现,没有困难。
#include<iostream>class Cpmv
{
public:struct Info{std::string qcode;std::string zcode;};
private:Info* pi;
public:Cpmv();Cpmv(std::string q, std::string z);Cpmv(const Cpmv&);Cpmv(Cpmv&& rhs);~Cpmv();Cpmv& operator=(const Cpmv& cp);Cpmv& operator=(Cpmv&&);Cpmv operator+(const Cpmv& obj) const;void Display() const;
};Cpmv::Cpmv():pi(nullptr)
{ }Cpmv::Cpmv(std::string q, std::string z)
{pi->qcode = q;pi->zcode = z;
}Cpmv::Cpmv(const Cpmv& rhs)
{pi = new Info;pi->qcode = rhs.pi->qcode;pi->zcode = rhs.pi->zcode;
}Cpmv::Cpmv(Cpmv&& rhs)
{pi = rhs.pi;rhs.pi = nullptr;
}Cpmv::~Cpmv()
{delete pi;
}Cpmv& Cpmv::operator=(const Cpmv& cp)
{Info* ptmp = pi;pi = new Info;pi->qcode = cp.pi->qcode;pi->zcode = cp.pi->zcode;delete ptmp;
}Cpmv& Cpmv::operator=(Cpmv&& rhs)
{delete pi;pi = rhs.pi;rhs.pi = nullptr;
}Cpmv Cpmv::operator+(const Cpmv& rhs) const
{Cpmv tmp;tmp.pi->qcode = pi->qcode + rhs.pi->qcode;tmp.pi->zcode = pi->zcode + rhs.pi->zcode;return tmp;
}void Cpmv::Display() const
{std::cout << pi->qcode << ", " << pi->zcode;return;
}
exercise 3
variadic template 简单的 packing,unpacking,recursion应用
#include<iostream>
#include<string>long double sum = 0;
void show_list() {}template<typename T>
void show_list(const T value)
{sum += value;//std::cout << value << '\n';
}template<typename T, typename... Args>
void show_list(const T value, const Args... args)
{//std::cout << value << ", ";sum += value;show_list(args...);
}int main()
{int n = 143;double x = 2.2345;int xyz = 23452;std::string mr = "Mr Q, go ahead\n";show_list(x,n,xyz);//show_list(n, x, mr);std::cout << sum;return 0;
}
后续更新改进点,不使用全局变量,如何记载数据
需要确认,从设计角度,template function能否有跟类型无关的参数,这是否是正确的、好的设计思路
exercise 4
找不到题目的位置, 把书上18.5抄了一份,作为lambda表达式的例子。
单为了使用 lambda 表达式,不需要这么多的头文件。
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>const long size = 302300L;int main()
{std::vector<int> numbers(size);std::srand(std::time(0));std::generate(numbers.begin(), numbers.end(), std::rand);int count3a = 0;int count3b = 0;int count13 = 0;auto Ismod3 = [](int x) -> bool { return x % 3 == 0; };auto mod3n13a = [&count3a, &count13](int x) {count3a += x % 3 == 0;count13 += x % 13 == 0;};auto mod3n13b = [&count3b, &count13](int x) {if (x % 3 == 0) ++count3b; // explicit conditionalif (x % 13 == 0) ++count13;};int the3 = std::count_if(numbers.begin(), numbers.end(), Ismod3);std::for_each(numbers.begin(), numbers.end(), mod3n13a);std::for_each(numbers.begin(), numbers.end(), mod3n13b);std::cout << "Count from std::count_if: " << the3 << "\n";std::cout << "Count from mod3n13a: " << count3a << ", " << count13 << std::endl;std::cout << "Count from mod3n13b: " << count3b << ", " << count13 << std::endl;return 0;
}
conclusion
日后写代码,需要注意边界条件,尤其是 依赖于中间状态及转换。需要小心验证,考虑到编译器会对我们的代码进行优化,有可能会产生意料之外的结果。