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

如何无需重复指定返回值,仅传入函数调用非类型模板参数的函数模板?

无需预处理器实现Call<f>()的调用方式

当然可以实现!不用依赖预处理器宏,我们可以借助C++17及以后的语言特性来简化这个调用,下面是最简洁的解决方案:

利用C++17的auto非类型模板参数

C++17引入了auto非类型模板参数,允许编译器自动推导非类型模板参数的类型,结合返回值类型推导,我们可以直接写出不需要手动指定返回值的模板:

template <auto Func>
auto Call() {
    return Func();
}

// 测试代码
int f() { return 1; }
double g() { return 3.14; }

int main() {
    Call<f>(); // 正常编译,返回int类型的1
    Call<g>(); // 正常编译,返回double类型的3.14
}

原理说明

  • 这里的auto Func让编译器自动推导传入的函数f/g的类型(比如f的类型是int(*)()),不需要我们显式声明函数的返回值或类型。
  • 返回值的auto会自动推导Func()的返回类型,完美替代了原来需要手动指定的R参数。

兼容C11/14的替代方案(如果不能用C17)

如果你的环境还停留在C11或C14,虽然没有auto非类型模板参数,但可以通过decltype推导返回值,只是调用时需要多写一点:

template <typename FuncType, FuncType Func>
auto Call() -> decltype(Func()) {
    return Func();
}

int main() {
    Call<decltype(f), f>(); // 编译正常,利用decltype推导函数类型
}

不过这种写法还是比C17的版本繁琐,所以优先推荐C17及以上的方案。

为什么原代码的Call<f>()会报错?

你原来的模板是先声明返回值类型R,再声明函数参数func,模板参数的推导是按顺序进行的——编译器无法从后面的f推导出前面的R,所以必须显式指定R才能编译。而新的方案通过让编译器自动推导参数类型和返回值,避免了这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:45:13