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

如何在编译期推导模板参数中可调用对象的返回类型?

如何让函数包装器自动推导返回类型?

我有一个用于包装自由函数(如open()、close())的模板,代码如下:

template <auto fn, typename ReturnType=void>
struct func_wrapper {

    template<typename... Args>
    constexpr ReturnType operator()(Args&&... args) const {
        if constexpr( std::is_same<ReturnType, void>::value) {
            fn(std::forward<Args>(args)...);
        } else {
            return fn(std::forward<Args>(args)...);
        }
    }
};

使用时需要手动指定返回类型:

void CloseFunc2(int a);
int OpenFunc2(const std::string&, int flags);

using FileWrapper2 = DevFileWrapper<func_wrapper<OpenFunc2, int>,
                                    func_wrapper<CloseFunc2>>;

代码能正常运行,但我希望创建func_wrapper时无需手动指定ReturnType。尝试用std::invoke_result推导返回类型但失败,错误代码如下:

template<typename... Args>
constexpr auto operator()(Args&&... args) const 
    -> std::invoke_result<fn(std::forward<Args>(args)...)>::type {
    if constexpr( std::is_same<ReturnType, void>::value) {
        fn(std::forward<Args>(args)...);
    } else {
        return fn(std::forward<Args>(args)...);
    }
}

编译报错:

template-parameter-callable.cpp:48:71: error: template argument for 
template type parameter must be a type
constexpr auto operator()(Args&&... args) const ->   
    std::invoke_result<fn(std::forward<Args>(args)...)>::type {                                                                           
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/
usr/include/c++/v1/type_traits:4009:17: 
note: template parameter is declared here
template <class _Fn, class... _Args>
                ^

1 error generated.

解决方案

错误原因

std::invoke_result的模板参数使用错误:它需要传入可调用对象的类型(如decltype(fn))和参数类型列表,而非直接传入函数调用表达式fn(...)。

优化后的包装器

直接利用C++14的auto返回类型推导,去掉冗余的ReturnType模板参数,让编译器自动推导返回值:

#include <type_traits>
#include <utility>

template <auto fn>
struct func_wrapper {
    template<typename... Args>
    constexpr auto operator()(Args&&... args) const {
        // 用decltype推导调用fn后的返回类型,判断是否为void
        if constexpr(std::is_void_v<decltype(fn(std::forward<Args>(args)...))>) {
            fn(std::forward<Args>(args)...);
        } else {
            return fn(std::forward<Args>(args)...);
        }
    }
};

使用方式

现在无需手动指定返回类型,直接传入函数即可:

void CloseFunc2(int a);
int OpenFunc2(const std::string&, int flags);

// 编译器自动推导返回类型
using FileWrapper2 = DevFileWrapper<func_wrapper<OpenFunc2>,
                                    func_wrapper<CloseFunc2>>;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 15:45:41