C++中能否让CTAD支持模板类型别名的类模板实参推导?
模板别名与类模板的核心区别
CTAD(类模板实参推导)的作用对象仅为原生类模板,模板别名本质是类型的别名,并非独立的类模板实体。C++17标准最初设计CTAD时,仅规定编译器会为类模板本身生成隐式推导指引、或匹配用户声明的显式推导指引,不会自动将别名模板的推导请求转发到其绑定的原类模板上。
另外你给出的示例代码存在语法疏漏,正确的模板别名定义需要使用using关键字:
// 错误写法:缺了using和类型名声明 // template<class T, size_t N> array_alias = std::array<T, N>; // 正确写法 template<class T, size_t N> using array_alias = std::array<T, N>;
让CTAD支持模板别名的方法
- C++20及以上版本直接支持
C20标准已经扩展了CTAD的适用范围,只要别名模板的参数列表、参数顺序与原类模板完全匹配,编译器会自动转发推导请求到原类模板,修正后的示例代码在C20编译模式下可正常运行:
#include <array> template<class T, size_t N> using array_alias = std::array<T, N>; int main() { array_alias arr{1,2,3}; // 正常推导为array_alias<int, 3>,等价于std::array<int, 3> return 0; }
- C++17版本手动添加推导指引
如果只能使用C++17标准,可以为别名模板显式声明推导指引,手动匹配原类模板的推导规则即可:
#include <array> template<class T, size_t N> using array_alias = std::array<T, N>; // 手动添加推导指引 template<class T, class... U> array_alias(T, U...) -> array_alias<T, 1 + sizeof...(U)>; int main() { array_alias arr{1,2,3}; // C++17下也可正常推导为array_alias<int, 3> return 0; }
内容的提问来源于stack exchange,提问作者Sugar
相关产品推荐
相关产品推荐

