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

实现多std::vector同索引元素打包时,如何判断各vector大小一致?

需求与问题

我需要实现一个函数,生成一个std::vector,其中每个元素是由传入的多个不同类型std::vector的同索引元素组成的std::tuple。目前的实现能完成基本功能,但有个隐患:如果调用者传入大小不一致的vector,程序会出现越界或逻辑错误。想知道如何判断所有传入的vector大小是否相同。

现有实现代码

template <typename... Args>
std::vector<std::tuple<Args...>> Foo(const std::vector<Args>&... vecs) 
{
    std::vector<std::tuple<Args...>> result;

    const auto elems = sizeof...(vecs);
    std::cout << "Elems = " << elems << std::endl;

    for (size_t i = 0; i < elems; ++i) 
    {
        result.emplace_back(std::make_tuple(vecs[i]...));
    }

    return result;
}

std::vector<int> v1 = {1, 4, 8};
std::vector<double> v2 = {1.1, 4.1, 8.1};
auto vec1 = Foo(v1, v2); // 预期结果:{ {1, 1.1}, {4, 4.1}, {8, 8.1} }

注意:现有代码存在明显bug——循环条件用了sizeof...(vecs)(传入的vector数量)而非vector实际的元素个数,比如传入2个大小为3的vector时,只会生成2个tuple,而非预期的3个。

解决方法

1. 运行期检查所有vector大小一致

C++17及以上(用折叠表达式简化代码)

先写一个辅助函数判断所有vector大小相同:

template <typename... Args>
bool allSameSize(const std::vector<Args>&... vecs) {
    if (sizeof...(vecs) == 0) return true;
    const auto targetSize = std::get<0>(std::make_tuple(vecs...)).size();
    return ((vecs.size() == targetSize) && ...);
}

然后在Foo函数开头加入检查,并修正循环条件:

template <typename... Args>
std::vector<std::tuple<Args...>> Foo(const std::vector<Args>&... vecs) 
{
    // 检查所有输入vector大小一致
    if (!allSameSize(vecs...)) {
        throw std::invalid_argument("所有传入的vector必须大小相同");
        // 调试阶段也可以用assert:assert(allSameSize(vecs...) && "vector大小不一致");
    }

    const auto elemCount = sizeof...(vecs) == 0 ? 0 : std::get<0>(std::make_tuple(vecs...)).size();
    std::vector<std::tuple<Args...>> result;
    result.reserve(elemCount); // 预分配内存提升性能

    for (size_t i = 0; i < elemCount; ++i) 
    {
        result.emplace_back(std::make_tuple(vecs[i]...));
    }

    return result;
}

C11/C14兼容版本

如果用较旧的C++标准,递归实现大小检查:

// 空参数时返回true
bool allSameSize() {
    return true;
}

// 检查第一个vector与后续所有vector大小一致
template <typename T, typename... Rest>
bool allSameSize(const std::vector<T>& first, const std::vector<Rest>&... rest) {
    using std::vector;
    if (sizeof...(rest) == 0) return true;
    const auto targetSize = first.size();
    // 递归检查后续每个vector
    bool restCheck = allSameSize(rest...);
    // 取第一个后续vector的大小和当前比较
    const auto firstRestSize = std::get<0>(std::make_tuple(rest...)).size();
    return restCheck && (targetSize == firstRestSize);
}

2. 编译期检查(仅适用于大小已知的constexpr vector)

如果所有传入的vector大小是编译期常量(比如用constexpr std::vector或std::array),可以在编译期就报错:

template <typename... Args>
constexpr bool allSameSize(const std::vector<Args>&... vecs) {
    if constexpr (sizeof...(vecs) == 0) return true;
    const auto targetSize = std::get<0>(std::make_tuple(vecs...)).size();
    return ((vecs.size() == targetSize) && ...);
}

template <typename... Args>
std::vector<std::tuple<Args...>> Foo(const std::vector<Args>&... vecs) 
{
    static_assert(allSameSize(vecs...), "所有vector大小必须相同");
    // 后续逻辑同前
}

额外注意事项

  • 如果不需要抛出异常,assert适合调试阶段快速发现问题,但发布版本中assert会被忽略,建议生产环境用异常或返回错误状态。
  • 处理空参数的情况:当没有传入任何vector时,返回空vector即可,避免访问空指针。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 09:03:17