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

C++14环境下Tuple of Vectors的Tuple插入与获取代码优化及函数泛化问询

更优雅的C++14 Tuple-of-Vectors实现方案

你的代码已经能正常运行,但确实有不少可以优化和泛化的空间——尤其是把for_each_in_tuple_and_arg扩展成支持任意多个同尺寸tuple的通用版本,同时让整体代码更简洁、复用性更强。下面是针对C++14环境的改进方案:

1. 泛化的for_each_in_tuples函数

我们可以把针对两个tuple的遍历逻辑,扩展成支持任意数量同大小tuple的通用函数,同时加入编译期检查确保所有tuple的尺寸一致(避免运行时错误)。由于C++14没有折叠表达式,我们用递归模板+辅助结构体来实现:

#include <tuple>
#include <vector>
#include <utility>
#include <type_traits>

// 辅助结构体:编译期检查所有tuple的尺寸是否等于指定值N
template <std::size_t N, class... Tuples>
struct all_tuples_same_size;

// 递归终止条件:没有更多tuple需要检查
template <std::size_t N>
struct all_tuples_same_size<N> : std::true_type {};

// 递归检查每个tuple的尺寸是否等于N
template <std::size_t N, class Tuple, class... Rest>
struct all_tuples_same_size<N, Tuple, Rest...> :
    std::integral_constant<bool,
        std::tuple_size<typename std::decay<Tuple>::type>::value == N
        && all_tuples_same_size<N, Rest...>::value> {};

// 递归终止:当索引等于tuple尺寸时停止遍历
template <std::size_t I = 0, class Fn, class... Tuples>
constexpr typename std::enable_if<I == std::tuple_size<typename std::tuple_element<0, std::tuple<Tuples...>>::type>::value, void>::type
for_each_in_tuples(Fn&&, Tuples&&...) {}

// 递归遍历:对每个索引I,提取所有tuple的第I个元素传给回调函数
template <std::size_t I = 0, class Fn, class... Tuples>
constexpr typename std::enable_if<I != std::tuple_size<typename std::tuple_element<0, std::tuple<Tuples...>>::type>::value, void>::type
for_each_in_tuples(Fn&& fn, Tuples&&... tuples) {
    using FirstTuple = typename std::decay<decltype(std::get<0>(std::forward_as_tuple(tuples...)))>::type;
    constexpr std::size_t TupleSize = std::tuple_size<FirstTuple>::value;
    
    // 编译期断言:确保所有传入的tuple尺寸相同
    static_assert(all_tuples_same_size<TupleSize, Tuples...>::value,
                  "All tuples passed to for_each_in_tuples must have the same size");
    
    // 将当前索引的所有tuple元素转发给回调函数
    fn(std::get<I>(std::forward<Tuples>(tuples))...);
    // 递归处理下一个索引
    for_each_in_tuples<I + 1>(std::forward<Fn>(fn), std::forward<Tuples>(tuples)...);
}

这个泛化版本的优势:

  • 通用性拉满:支持2个及以上同大小的tuple,比如同时遍历3个tuple的对应元素
  • 编译期安全:静态断言会在编译阶段检查所有tuple的尺寸是否一致,提前暴露错误
  • 复用性高:原来的for_each_in_tuple可以直接被这个函数替代(只传一个tuple即可)

2. 简化后的tuple_of_vectors类

现在我们可以用这个泛化函数来重构类中的方法,让代码更简洁统一,减少重复逻辑:

class tuple_of_vectors {
public:
    using tov_type = std::tuple<std::vector<int>, std::vector<int>, std::vector<int>>;
    using value_type = std::tuple<int, int, int>;

    void reserve(std::size_t n) {
        // 单tuple场景:只传tov_给泛化函数
        for_each_in_tuples([n](auto& vec) { vec.reserve(n); }, tov_);
    }

    value_type at(std::size_t n) const noexcept {
        value_type res{};
        // 双tuple场景:同时遍历结果tuple和数据源tuple
        for_each_in_tuples([n](auto& val, const auto& vec) {
            val = vec.at(n);
        }, res, tov_);
        return res;
    }

    void insert(const value_type& tup) {
        const std::size_t insert_pos = 0; // 保留你原有的插入位置逻辑
        // 双tuple场景:同时遍历vector容器tuple和待插入的value tuple
        for_each_in_tuples([insert_pos](auto& vec, const auto& val) {
            vec.insert(vec.begin() + insert_pos, val);
        }, tov_, tup);
    }

private:
    tov_type tov_;
};

额外的实用优化建议

  • 如果你实际需求是在容器末尾添加元素(而非开头),把insert改成push_back效率更高:
    void push_back(const value_type& tup) {
        for_each_in_tuples([](auto& vec, const auto& val) {
            vec.push_back(val);
        }, tov_, tup);
    }
    
  • 把类改成模板类,支持任意类型和数量的vector组合,扩展性更强:
    template <typename... Ts>
    class tuple_of_vectors {
    public:
        using tov_type = std::tuple<std::vector<Ts>...>;
        using value_type = std::tuple<Ts...>;
    
        void reserve(std::size_t n) {
            for_each_in_tuples([n](auto& vec) { vec.reserve(n); }, tov_);
        }
    
        value_type at(std::size_t n) const noexcept {
            value_type res{};
            for_each_in_tuples([n](auto& val, const auto& vec) {
                val = vec.at(n);
            }, res, tov_);
            return res;
        }
    
        void push_back(const value_type& tup) {
            for_each_in_tuples([](auto& vec, const auto& val) {
                vec.push_back(val);
            }, tov_, tup);
        }
    
    private:
        tov_type tov_;
    };
    
    这样你就可以创建tuple_of_vectors<int, double, std::string>这类自定义实例了。

3. 代码正确性验证

改进后的代码完全兼容C++14,且保留了你原有的所有功能,同时更灵活易维护。你可以像之前一样使用这个类:

int main() {
    tuple_of_vectors tov;
    tov.reserve(10);
    tov.insert(std::make_tuple(1, 2, 3));
    auto val = tov.at(0); // val的值为(1, 2, 3)
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 09:27:45