C++17类模板部分实参推导:如何混合显式指定与自动推导参数
结论
C++17标准下不支持类模板部分显式指定参数、部分推导的用法,推导指南(deduction guides)也无法实现该需求。
核心规则说明
- C++17的类模板实参推导(CTAD)只有在完全省略模板尖括号时才会触发,只要你在尖括号内写了任意数量的参数,编译器就会要求你提供全部模板参数,不会启动推导流程。
- 你目前了解的「CTAD要么全显式指定、要么全推导」的规则是完全正确的,推导指南仅作用于全推导的场景,无法解决部分指定的需求。
C++17下更优雅的替代方案
不需要写外部构造函数,你可以在类内实现静态工厂方法,封装性更好:
template<typename T1, typename T2> struct S { T2 t2; S(const T2& _t2) : t2{_t2} {} // 静态工厂方法,利用函数模板的部分推导特性 template<typename U1, typename U2> static S<U1, U2> create(const U2& t2) { return S<U1, U2>{t2}; } void operator()(const T1& t1) { std::cout << t1 << ", " << t2 << '\n'; } }; int main() { // 调用方式更简洁,和类绑定不需要额外引入外部函数 auto s2 = S::create<int>(3.14); std::function<void(int)> func2 = s2; func2(42); }
C++20及以上版本的原生支持
从C++20开始,类模板实参推导已经支持部分显式指定前缀参数,你期望的写法可以直接生效:
// C++20及以上可以直接这么写,不需要任何工厂函数 S<int> s2 {3.14}; // T1显式指定为int,T2从3.14推导为double
内容的提问来源于stack exchange,提问作者Zamfir Yonchev
相关产品推荐
相关产品推荐

