模板与泛型编程

1. 定义模板


1.1 函数模板



1.非类型模板参数

  模板参数可以是类型,也可以是非类型,如整型、关联对象或函数类型的指针或左值引用。
  模板参数是类型时,模板参数类型是typename或class。模板参数是非类型时,模板参数类型就是对应的模板参数的类型:整型、指针或引用。

template<typename T, size_t N>
void fun(T (&arr)[N]) { cout << N << endl; }

  函数fun接受任何类型的数组名,都能输出数组长度。
  数组长度不需要在调用时用尖括号给出,模板就能推断出数组长度。也就是说这样调用就可以fun(arr),而不需fun<10>(arr)。但数组长度外的其它非类型参数是需要在尖括号内给出的:

// 1. 模板函数。
// 整型
template<int n>
void fInteger1() { cout << n << endl; }
template<int n>
void fInteger2(int (&a)[n]) { cout << n << endl; }
// 指针。
template<int* p>
void fPointer() { cout << *p << endl; }
// 引用。
template<int (&r)[1]>
void fReference() { cout << r[0] << endl; }
// 函数指针。
template<void (*f)(int)>
void fFunpointer(int x) { f(x); }
// 2. 实参。
int a[3] = { 1, 2, 3 };
int p[1] = { 4 };
int r[1] = { 5};
void f(int x) { cout << x << endl; }
// 3. 测试。
int main() {
	fInteger1<3>(); // 给定模板参数。
	fInteger2(a); // 从实参推断模板参数。
	fPointer<p>(); // 给定模板参数。
	fReference<r>(); // 给定模板参数。
	fFunpointer<f>(6); // 给定模板参数。
}

2. 可变参数模板


2.1 参数包


class Example { public: Example(int a, int b) { cout << a << " " << b << endl; } };
void print(int a, int b) { cout << a << " " << b << endl; }

template<typename... Args>
void testArgsPkg(Args... args) {
	Example e = Example((args)...); // 1.参数包做初始化参数。
	print((args)...); // 2.参数包做函数参数。
	cout << sizeof...(args) << endl; // 3.输出参数包内参数个数而不是字节数。
}

int main() {
	testArgsPkg(1, 3);
}

  第 4 至 9 行定义了一个使用参数包的函数 testArgsPkg。可以向该函数传入任意个实参。

2.2 遍历参数


#include <iostream>
#include <sstream>

template <typename... Args>
void print1(Args... args) {
    std::stringstream ss;
    std::initializer_list<int>{(
        [&] {
            ss << args;
        }(),
        0)...};
    std::cout << ss.str() << "." << std::endl;
}

template <class T>
void printArgs2(std::ostream &os, const T &t) {
    os << t;
}

template <typename... Args>
void print2(Args... args) {
    std::stringstream ss;
    int arr[] = {(printArgs2(ss, args), 0)...};
    std::cout << ss.str() << "." << std::endl;
}

void printArgs3(std::ostream &os) {
}

template <typename T, typename... Args>
void printArgs3(std::ostream &os, const T &t, Args &&...args) {
    os << t;
    if (sizeof...(args) > 0) {
        printArgs3(os, std::forward<Args>(args)...);
    }
}

template <typename... Args>
void print3(const Args &...args) {
    std::stringstream ss;
    printArgs3(ss, args...);
    std::cout << ss.str() << "." << std::endl;
}

template <typename T>
void printArgs4(std::ostream &os, const T &t) {
    os << t;
}

template <typename T, typename... Args>
void printArgs4(std::ostream &os, const T &t, const Args &...rest) {
    os << t;
    printArgs4(os, rest...);
}

template <typename... Args>
void print4(const Args &...args) {
    std::stringstream ss;
    printArgs4(ss, args...);
    std::cout << ss.str() << "." << std::endl;
}

int main() {
    print1(1, '2', "abc");
    print2(1, '2', "abc");
    print3(1, '2', "abc");
    print4(1, '2', "abc");
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值