You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>类型,可以用以下几种方式:

  1. 显式类型转换
    直接通过static_cast指定目标类型:
auto r = static_cast<TemplatedClass<Rect, 66>>(DrawRect());

优点是直接直观,缺点是需要硬编码目标模板参数,不够灵活。

  1. 添加隐式转换运算符
    在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();会自动触发转换,得到目标类型。但要注意,隐式转换可能带来意外的类型转换问题,需要谨慎使用。

  1. 封装推导辅助函数
    写一个辅助函数,利用类模板推导指引来生成目标类型:
template<typename T>
auto deduce(TemplatedClass<T, 0> obj) {
    return TemplatedClass{obj}; // 这里会触发推导指引
}

然后在main中调用:

auto r = deduce(DrawRect());

这种方式既不用硬编码模板参数,也不会引入全局的隐式转换,是相对优雅的方案。

内容的提问来源于stack exchange,提问作者A A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 11:37:10