1. 全特化和偏特化
https://harttle.land/2015/10/03/cpp-template.html
2. 模板元编程
例子1 在编译阶段实现阶乘
使用enum编译实现
#include <iostream>
using namespace std;
template<unsigned N>
struct Factorial {
enum {VALUE=N*Factorial<N-1>::VALUE};
};
template<>
struct Factorial<0> {
enum {VALUE=1};
};
int main(){
Factorial <5> F;
cout << F.VALUE;
return 0;
}
使用static const T编译实现
#include <iostream>
using namespace std;
template<unsigned N>
struct Factorial {
enum haha{VALUE=N*Factorial<N-1>::VALUE};
};
template<>
struct Factorial<0> {
enum haha{VALUE=1};
};
int main(){
Factorial <5> F;
cout << F.VALUE << endl;
cout << typeid(F.VALUE).name()<<endl;
cout << typeid(F).name() << endl;
return 0;
}
运行结果
120
enum Factorial<5>::haha
struct Factorial<5>
或者这样写:
#include <iostream>
using namespace std;
template<unsigned N>
struct Factorial {
static const unsigned VALUE=N*Factorial<N-1>::VALUE;
};
template<>
struct Factorial<0> {
static const unsigned VALUE = 1;
};
int main(){
Factorial <5> F;
cout << F.VALUE << endl;
cout << typeid(F.VALUE).name()<<endl;
return 0;
}
因为编译的时候只能知道常量,所以VALUE要加上const,由于递归的需要,故加上static
例子2 再进一步泛化
实现乘方的功能
可以使用函数模板:
template<unsigned N>
inline double power(double v){
return v*power<N-1>(v);
}
template<>
inline double power<1>(double v){
return v;
}
由于需要在编译阶段进行运算,故需使用inline关键字
进一步泛化
上述代码只针对double型变量有效,为了方便可进一步进行泛化:
#include <iostream>
using namespace std;
template<unsigned N>
struct Power {
template<class T>
static T value(T x) {/*写成static const T value(T x)也可以 */
return x * Power<N - 1>::value(x);
}
};
template<>
struct Power<1> {
template<class T>
static T value(T x) {/*写成static const T value(T x)也可以 */
return x;
}
};
int main(){
int F=Power <4> ::value(3);
cout << F << endl;
cout << typeid(F).name()<<endl;
return 0;
}
由于函数模板不可偏特化,所以不能直接指定N=1的计算结果,所以可以把整体写一个类,再实现偏特化。具体做法是把赋值语句写在类的成员函数中,上面的代码const是否存在,运行结果都相同。
调用方式:
int x=5;
Power <4> ::value(x);
简化函数的调用
或者可对上述代码的调用进行简化,设计一个辅助的函数模板:
#include <iostream>
using namespace std;
template<unsigned N>
struct Power {
template<class T>
static const T value(T x) {
return x * Power<N - 1>::value(x);
}
};
template<>
struct Power<1> {
template<class T>
static const T value(T x) {
return x;
}
};
template<unsigned N, class T>
inline T Power1(T v) {
return Power<N>::value(v);
}
int main(){
int F=Power <4> ::value(3);
cout << F << endl;
cout << typeid(F).name()<<endl;
double f = 2;
//cout << Power1<2, double>(f);也可以
cout << Power1<2>(f);
return 0;
}