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

如何无需显式指定模板参数定义模板结构体常量变量?

问题与需求

现有如下结构体和类定义,用于存储类成员函数指针:

template <typename R>
struct Foo {
    R ref;
    int info;
};
class Bar {
public:
    void* run();
};

希望创建Foo类型的常量变量时,无需显式指定模板参数,直接用初始化列表完成初始化(如下方第一行代码),而不是必须写出冗长的成员函数指针类型(第二行可行但不够简洁):

const Foo theVar {&Bar::run, 0x1000}; // 期望的简洁写法,但原代码编译不通过
const Foo<void (Bar::*)()> theVar {&Bar::run, 0x1000}; // 可行但写法繁琐

使用模板的原因是类成员函数指针无法直接转换为void*,只能通过模板来存储其原始类型。同时要求该变量必须在链接阶段可见,不能在运行时赋值,模板是当前可行的实现方式,但显式指定模板参数不够简洁,易引发维护问题。

解决方法

方法1:C++17及以上 - 类模板实参推导(CTAD)

C17引入了类模板实参推导(Class Template Argument Deduction, CTAD),编译器可根据初始化列表中的参数自动推导模板类型。只需确保编译器开启C17或更高版本的编译选项,你的期望写法就能直接编译通过:

const Foo theVar {&Bar::run, 0x1000}; // C++17+ 编译正常

编译器会自动识别&Bar::run的类型为void (Bar::*)(),并将其作为Foo的模板参数R。

方法2:兼容C11/C14 - 辅助推导函数

如果需要兼容更早的C++标准,可以编写一个简单的辅助函数来推导模板类型:

template <typename R>
Foo<R> make_foo(R ref, int info) {
    return {ref, info};
}

然后通过该函数创建变量,编译器会自动推导R的类型:

const auto theVar = make_foo(&Bar::run, 0x1000);

这种方式同样能避免显式写出冗长的成员函数指针类型,同时兼容C++11及以上标准。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 06:55:17