C++17:如何让auto变量触发类模板推导指引?
C++17类推导指引能否作用于auto变量?
C++17支持为类模板创建推导指引,请问这类指引能否应用到auto变量上?
我尝试了以下代码,当前auto变量的输出是0,期望能触发已定义的推导指引让它输出66,同时DrawRect函数必须保持返回TemplatedClass<Rect, 0>类型。我知道auto默认会沿用函数的返回类型,想问问有没有办法覆盖这个行为?
#include <stdio.h> struct Rect { int Rect; }; template<typename T, int k = 0> class TemplatedClass : public T { public: static constexpr int S = k; T value; TemplatedClass() {} TemplatedClass(T val) : value(val) {} }; TemplatedClass(TemplatedClass<Rect, 0>) -> TemplatedClass<Rect, 66>; TemplatedClass<Rect, 0> DrawRect() { return {}; } int main() { auto r = DrawRect(); r.Rect = 0; TemplatedClass a = DrawRect(); a.Rect = 0; printf("r.S %d \n", r.S); // 期望输出66 printf("a.S %d \n", a.S); // 期望输出66 return 0; }
核心结论
auto的类型推导不会触发类模板推导指引,它会直接沿用初始化表达式的类型——也就是DrawRect()返回的TemplatedClass<Rect, 0>,所以r.S输出0是符合规则的。类模板推导指引仅在用类模板名(不指定模板参数)直接初始化对象时生效,比如代码里的TemplatedClass a = DrawRect();这一行,编译器会通过推导指引推导出模板参数为Rect, 66。
实现需求的几种方法
如果要在保留DrawRect返回类型的前提下,让auto变量得到TemplatedClass<Rect, 66>类型,可以用以下几种方式:
- 显式类型转换
直接通过static_cast指定目标类型:
auto r = static_cast<TemplatedClass<Rect, 66>>(DrawRect());
优点是直接直观,缺点是需要硬编码目标模板参数,不够灵活。
- 添加隐式转换运算符
在TemplatedClass中定义一个转换运算符,允许TemplatedClass<T, 0>隐式转换为TemplatedClass<T, 66>:
template<typename T, int k = 0> class TemplatedClass : public T { // ... 原有代码 ... public: // 添加转换运算符 operator TemplatedClass<T, 66>() const { return TemplatedClass<T, 66>{value}; } };
这样auto r = DrawRect();会自动触发转换,得到目标类型。但要注意,隐式转换可能带来意外的类型转换问题,需要谨慎使用。
- 封装推导辅助函数
写一个辅助函数,利用类模板推导指引来生成目标类型:
template<typename T> auto deduce(TemplatedClass<T, 0> obj) { return TemplatedClass{obj}; // 这里会触发推导指引 }
然后在main中调用:
auto r = deduce(DrawRect());
这种方式既不用硬编码模板参数,也不会引入全局的隐式转换,是相对优雅的方案。
内容的提问来源于stack exchange,提问作者A A
相关产品推荐
相关产品推荐

