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

能否实现类似std::invoke的函数,自动以默认构造类型调用参数?

实现自动以默认构造实参调用函数的invoke替代版本

完全可以实现这样的函数,核心思路是通过模板元编程提取可调用对象的参数类型,自动生成对应类型的默认构造值作为实参,再传递给std::invoke完成调用。

完整实现代码

#include <iostream>
#include <functional>
#include <tuple>
#include <utility>

// 函数特质模板:提取可调用对象的参数类型
template<typename T>
struct function_traits : function_traits<decltype(&T::operator())> {};

// 处理const版本的仿函数operator()
template<typename Class, typename Ret, typename... Args>
struct function_traits<Ret(Class::*)(Args...) const> {
    using args = std::tuple<Args...>;
};

// 处理非const版本的仿函数operator()
template<typename Class, typename Ret, typename... Args>
struct function_traits<Ret(Class::*)(Args...)> {
    using args = std::tuple<Args...>;
};

// 处理普通函数指针
template<typename Ret, typename... Args>
struct function_traits<Ret(*)(Args...)> {
    using args = std::tuple<Args...>;
};

// 辅助实现函数:利用索引序列展开参数
template<typename F, std::size_t... Is>
auto invoke_with_defaults_impl(F&& f, std::index_sequence<Is...>) {
    using ArgsTuple = typename function_traits<std::decay_t<F>>::args;
    return std::invoke(std::forward<F>(f), std::tuple_element_t<Is, ArgsTuple>{}...);
}

// 对外接口函数
template<typename F>
auto invoke_with_defaults(F&& f) {
    using ArgsTuple = typename function_traits<std::decay_t<F>>::args;
    constexpr auto ArgsCount = std::tuple_size_v<ArgsTuple>;
    return invoke_with_defaults_impl(std::forward<F>(f), std::make_index_sequence<ArgsCount>{});
}

// 测试用仿函数
struct Test{
    void operator()(int i) {
        std::cout << std::to_string(i) << "\n";
    }
};

// 测试多参数普通函数
void multi_param_func(std::string s, double d) {
    std::cout << "String: " << s << ", Double: " << d << "\n";
}

int main(){
    Test test;
    invoke_with_defaults(test); // 输出0

    invoke_with_defaults(multi_param_func); // 输出String: , Double: 0
    return 0;
}

关键部分说明

  1. function_traits模板:

    • 针对不同类型的可调用对象(仿函数、普通函数指针)做特化,提取出调用时需要的参数类型,并打包成std::tuple类型args。
    • 分别处理了const/非const版本的仿函数operator(),确保覆盖常见的仿函数场景。
  2. invoke_with_defaults_impl辅助函数:

    • 利用std::index_sequence生成参数索引,通过std::tuple_element_t逐个取出参数类型,构造默认值({}),最后通过折叠表达式展开所有参数传递给std::invoke。
  3. 对外接口invoke_with_defaults:

    • 推导可调用对象的参数数量,生成对应的索引序列,转发给辅助函数完成实际调用。

注意事项

  • 要求所有参数类型必须支持默认构造,如果某个参数类型没有默认构造函数,编译会直接报错,这是符合预期的行为。
  • 支持C17及以上版本,因为用到了std::index_sequence、std::tuple_size_v等C17特性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 20:35:28