整数范围参数模板类显式实例化及静态库编译问题咨询
问题解答
能否编译为静态库
完全可以,只要按照以下结构安排代码即可:
- 头文件仅存放模板类
A的声明,不存放实现代码 - 单独的源文件存放模板类
A的完整实现,同时在该源文件内完成所有区间内的显式实例化 - 编译该源文件后打包为静态库,其他业务代码仅需引入对应头文件,链接该静态库即可正常使用指定区间内的
A<N1,N2>实例,无需可见模板实现代码。
自动批量生成实例化的方案
不需要手动逐个编写所有排列的实例化语句,常用的实现方案有三种:
方案1:C++模板元编程(编译期自动展开)
基于C11及以上版本的std::integer_sequence特性,可以在编译期自动生成所有组合的实例化,C17版本示例代码如下:
#include <utility> #include <initializer_list> template <int N1, int N2> class A { // 类实现代码 }; // 展开单个N1对应的所有N2区间实例 template <int N1, int... N2List> void instance_n2(std::integer_sequence<int, N2List...>) { std::initializer_list<int>{(static_cast<void>(A<N1, N2List>{}), 0)...}; } // 展开所有N1区间 template <int... N1List, int K2> void instance_all(std::integer_sequence<int, N1List...>, std::integral_constant<int, K2>) { std::initializer_list<int>{(instance_n2<N1List>(std::make_integer_sequence<int, K2 + 1>{}), 0)...}; } // 示例:实例化N1∈[0,5]、N2∈[0,3]的所有组合,修改K1、K2取值即可适配其他区间 constexpr int K1 = 5; constexpr int K2 = 3; template void instance_all(std::make_integer_sequence<int, K1 + 1>{}, std::integral_constant<int, K2>{});
如果使用C++11/14版本,仅需将折叠表达式相关逻辑替换为模板递归实现即可,无需额外依赖。
方案2:预处理器宏生成
如果编译器版本较低,可以借助预处理器的循环能力批量生成代码,以Boost.Preprocessor为例:
#include <boost/preprocessor/repetition/repeat.hpp> #include <boost/preprocessor/seq/for_each_product.hpp> #include <boost/preprocessor/seq/elem.hpp> #define K1 5 #define K2 3 #define INSTANCE_DECL(_, param) template class A<BOOST_PP_SEQ_ELEM(0, param), BOOST_PP_SEQ_ELEM(1, param)>; // 自动展开为所有组合的显式实例化语句 BOOST_PP_SEQ_FOR_EACH_PRODUCT(INSTANCE_DECL, (BOOST_PP_REPEAT(K1 + 1, ((0)), ~)) (BOOST_PP_REPEAT(K2 + 1, ((0)), ~)) )
展开后会自动生成所有template A<x,y>;的实例化语句。
方案3:构建脚本生成
如果K1、K2取值极大,编译期展开负担过高,可以在构建阶段通过Python、Shell等脚本生成包含所有实例化语句的独立源文件,再加入编译流程即可,这种方式对编译性能影响最小。
内容的提问来源于stack exchange,提问作者Jonas Hjulstad
相关产品推荐
相关产品推荐

