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

如何解析方括号字符串为std::vector并修复模板编译错误

问题描述

需要将逗号分隔的方括号格式字符串解析为std::vector类型,示例预期效果:

  • 输入[1,2,3],解析结果为std::vector<int>{1,2,3}
  • 输入[[1,2,3],[4,5,6]],解析结果为std::vector<std::vector<int>> {std::vector<int> {1,2,3}, std::vector<int> {4,5,6}}
    尝试通过泛型代码实现该功能时,代码无法通过编译。
初始实现代码
#include <iostream>
#include <vector>
#include <string>
#include <regex>
#include <type_traits>
#include <algorithm>

template<typename Test, template<typename...> class Ref>
struct is_specialization : std::false_type {};

template<template<typename...> class Ref, typename... Args>
struct is_specialization<Ref<Args...>, Ref> : std::true_type {};


template<typename T, typename UnaryOperation>
std::enable_if_t<is_specialization<T, std::vector>::value, T> parse1D(std::string a, UnaryOperation unary_op) { // 一维vector场景:拆分字符串后做类型转换
    T ans;
    if (a.length() < 2 || a[0] != '[' || a[a.length() - 1] != ']') return ans; // 非法格式返回空

    std::regex re(",");
    std::sregex_token_iterator it(a.begin()+1, a.end()-1, re, -1), end;
    std::transform(it, end, std::back_inserter(ans), unary_op);
    return ans;
}

template<typename T, typename UnaryOperation>
std::enable_if_t<is_specialization<T,std::vector>::value, T> parse(std::string a, UnaryOperation unary_op) {
    T ans;
    if (a.length() < 2 || a[0] != '[' || a[a.length() - 1] != ']') return ans; // 非法格式返回空

    if (is_specialization<T::value_type, std::vector>::value) { // 递归处理多维场景
        // 未实现递归逻辑
        return ans;
    }else { // 一维vector场景走base case
        return parse1D<T>(a, unary_op);
    }
}
调用方式与报错

调用代码如下:

auto ret = parse<std::vector<std::vector<int>>>(std::string("[[1,2,3],[4,5,6]]"), [](const auto& el) {
    return std::stoi(el);
});

编译器在std::transform调用位置抛出错误:不存在右操作数为int类型的可用赋值运算符。

错误原因

C++中普通if-else是运行时分支,两个分支的代码都会被编译器实例化编译。即使逻辑上多维vector场景会进入递归分支,else分支调用parse1D<T>的代码依然会被编译:此时T为std::vector<std::vector<int>>,元素类型是std::vector<int>,但传入的转换函数返回int类型,std::transform尝试将int值赋值给vector元素,触发类型不匹配错误。

解决方案

使用C++17引入的if constexpr代替普通if做编译期分支判断:编译器只会实例化符合当前常量条件的分支,直接丢弃不满足条件的分支代码,从根本上避免无效分支的类型错误。
另外原代码中直接按逗号分割的逻辑仅适用于一维vector,多维场景下需要先通过括号计数拆分出每个内层vector的子串,再递归解析,不能直接全局切分逗号。

修正后的完整parse函数实现如下:

template<typename T, typename UnaryOperation>
std::enable_if_t<is_specialization<T,std::vector>::value, T> parse(std::string a, UnaryOperation unary_op) {
    T ans;
    if (a.length() < 2 || a[0] != '[' || a[a.length() - 1] != ']') return ans; // 非法格式返回空

    // 编译期判断:当前vector的元素是否也是vector类型(即是否为多维场景)
    if constexpr (is_specialization<typename T::value_type, std::vector>::value) { 
        std::vector<std::string> sub_items;
        int bracket_count = 0;
        size_t split_start = 1;
        // 括号匹配计数,拆分出每个内层子vector对应的字符串
        for (size_t i = 1; i < a.size() - 1; i++) {
            if (a[i] == '[') bracket_count++;
            else if (a[i] == ']') bracket_count--;
            else if (a[i] == ',' && bracket_count == 0) {
                sub_items.push_back(a.substr(split_start, i - split_start));
                split_start = i + 1;
            }
        }
        sub_items.push_back(a.substr(split_start, a.size() - 1 - split_start));
        // 递归解析每个子串
        for (auto& sub_str : sub_items) {
            ans.push_back(parse<typename T::value_type>(sub_str, unary_op));
        }
        return ans;
    } else { 
        // 一维场景直接调用1D解析逻辑,该分支仅在元素为非vector类型时才会被编译
        return parse1D<T>(a, unary_op);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 19:54:14