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

如何让C++模板函数processArray兼容传值与传引用的回调?

问题描述

现有如下C++代码:processArray是用于处理数组的模板函数,它接受回调函数processItem处理每个数组元素。

template<typename TItem>
size_t processArray(const TItem* value, const size_t length, size_t (*processItem)(const TItem)) {
    size_t output = length;

    for (auto i = 0; i < length; ++i) {
        output += processItem(value[i]);
    }

    return output;
}

size_t processInt(const int value) {
    return value;
}

size_t processString(const std::string& value) {
    return value.length();
}

处理int数组时传入processInt可正常编译,但处理std::string数组传入processString会报错——因为回调参数声明为const TItem,无法接受引用类型的参数。

若将processItem参数改为size_t (*processItem)(const TItem&),则传入processInt会报错,传入processString正常。

希望仅声明一次processArray,使其兼容传值和传引用类型的回调,而非重复声明模板,请问该如何实现?


解决方案

方案1:将回调类型设为独立模板参数

直接把回调函数的类型也作为模板参数,让编译器自动推导适配,这是最灵活的方式,还能兼容lambda、函数对象等其他可调用类型:

#include <string>

template<typename TItem, typename ProcessFunc>
size_t processArray(const TItem* value, const size_t length, ProcessFunc processItem) {
    size_t output = length;

    for (auto i = 0; i < length; ++i) {
        output += processItem(value[i]);
    }

    return output;
}

// 原有的processInt、processString无需修改
size_t processInt(const int value) {
    return value;
}

size_t processString(const std::string& value) {
    return value.length();
}

// 测试示例
int main() {
    int intArr[] = {1,2,3};
    processArray(intArr, 3, processInt); // 正常编译

    std::string strArr[] = {"foo", "bar", "baz"};
    processArray(strArr, 3, processString); // 正常编译
    return 0;
}

方案2:使用std::function适配(C++11及以上)

如果需要明确回调的签名范围,可以用std::function结合decltype推导数组元素类型,自动适配传值/传引用的回调:

#include <string>
#include <functional>

template<typename TItem>
size_t processArray(const TItem* value, const size_t length, std::function<size_t(decltype(value[0]))> processItem) {
    size_t output = length;

    for (auto i = 0; i < length; ++i) {
        output += processItem(value[i]);
    }

    return output;
}

// 原processInt、processString和测试代码不变

方案3:C++20概念约束(增强类型安全)

如果使用C++20,可以用概念明确约束回调必须能处理数组元素类型,同时用std::invoke统一调用逻辑:

#include <string>
#include <concepts>
#include <functional>

template<typename TItem, typename ProcessFunc>
requires std::invocable<ProcessFunc, const TItem> || std::invocable<ProcessFunc, const TItem&>
size_t processArray(const TItem* value, const size_t length, ProcessFunc processItem) {
    size_t output = length;

    for (auto i = 0; i < length; ++i) {
        output += std::invoke(processItem, value[i]);
    }

    return output;
}

// 原processInt、processString和测试代码不变

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 10:18:25