考察 std::initializer_list <>
这份template函数参照简单的例子书写。这种方式会简单很多。
注意到我后面两次调用函数 average_list, 它的 std::initializer_list <>并不相同
#include
#include
#include
double sum(std::initializer_list i)
{
double tot = 0;
std::for_each(i.begin(), i.end(), [&tot](double db)
{
tot += db;
}
);
return tot;
}
template
T average_list(const std::initializer_list 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({'A', 70, 65.33}); // u pass in a type explicitly
std::cout << p;
return 0;
}
在简单的类成员函数的基础上添加了 move semantic,移动构造 和 移动赋值。
driver的驱动函数可以自己实现,没有困难。
#include
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;
}
variadic template 简单的 packing,unpacking,recursion应用
#include
#include
long double sum = 0;
void show_list() {}
template
void show_list(const T value)
{
sum += value;
//std::cout << value << '\n';
}
template
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能否有跟类型无关的参数,这是否是正确的、好的设计思路
找不到题目的位置, 把书上18.5抄了一份,作为lambda表达式的例子。
单为了使用 lambda 表达式,不需要这么多的头文件。
#include
#include
#include
#include
const long size = 302300L;
int main()
{
std::vector 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 conditional
if (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;
}
日后写代码,需要注意边界条件,尤其是 依赖于中间状态及转换。需要小心验证,考虑到编译器会对我们的代码进行优化,有可能会产生意料之外的结果。