文章

C++类模板偏特化

C++类模板偏特化

C++中的函数模板和类模板被广泛应用,其中函数模板只支持重载和全特化,而C++类模板支持偏特化,以下是一个例子,用于记录类模板偏特化。


一个tuple打印器

tuple_print 实现tuple数据打印

1
2
3
4
5
6
7
8
9
10
11
template<int IDX, int MAX_SIZE, typename ...Args>
struct tuple_print {
    void operator()(ostream& os, const tuple<Args...> & t) {
        // print idx item
        os << get<IDX>(t) << (IDX == MAX_SIZE - 1 ? "" : ",");
    
        tuple_print<IDX + 1, MAX_SIZE, Args...>()(os, t);
    }
    
};

tuple_print 偏特化

为了让打印器能够停止递归,需要实现一个偏特化类

1
2
3
4
5
6
7
8
// 偏特化
template<int MAX_SIZE, typename ...Args>
struct tuple_print<MAX_SIZE, MAX_SIZE, Args...> {
    void operator()(ostream& os, const tuple<Args...> & t) {
        // do nothing
    }
};

重载流运算符

1
2
3
4
5
6
template<typename ...Args>
ostream& operator<<(ostream& os, const tuple<Args...>& t) {
    os << "[";
    tuple_print<0, sizeof...(Args), Args...>()(os, t);
    return os << "]";
}

测试程序

1
2
3
4
5
6
7
8
int main() {

    tuple<int, const char*> t(3, "hhh");

    cout << t << endl;

    return 0;
}

输出结果

1
[3,hhh]

note
不能通过判断IDX == MAX_SIZE - 1来return的方式,C++ 模板是编译期展开的。即使这个 if 在运行时会跳过递归调用,编译器仍会尝试实例化 tuple_print<IDX+1, MAX_SIZE, Args…>,即使它永远不会被执行!所以需要通过偏特化的方式停止这个过程。

本文由作者按照 CC BY 4.0 进行授权