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

C++17下无需auto简化声明ctre::regex_results变量的方法

问题

我使用C++17开发,需要声明如下结构的ctre::regex_results类型变量:

ctre::regex_results<const char*,
                    ctre::captured_content<1, void>,
                    ctre::captured_content<2, void> > mts;

ctre::regex_results<const char*,
                    ctre::captured_content<1, void>,
                    ctre::captured_content<2, void>,
                    ...,
                    ctre::captured_content<8, void> > mts;

其中模板参数列表中ctre::captured_content的数量由编译时确定。我希望找到不使用auto、且不在块作用域声明模板的简化声明方式(块作用域声明模板会报错:a template declaration cannot appear at block scope)。所需类型由以下模板变量决定:

template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers>
static constexpr inline auto search =
    regular_expression<typename regex_builder<input>::type,
                       search_method,
                       ctll::list<singleline, Modifiers...>>();

附示例代码:

#include <bits/stdc++.h>
#include "ctre.hpp" //  single-header of compile-time-regular-expressions

using namespace std;

#define LINE_RGX "((?:a+).(?:b+).(?:c+).(?:d+)\\s*)+"

#define RGX1 "(a+)\\.(b+)\\.(c+)\\.(d+)\\s*"
#define RGX2 "(a+\\.b+)\\.(c+\\.d+)\\s*"

static constexpr auto ctre_line_rgx = ctll::fixed_string{ LINE_RGX };
static constexpr auto ctre_rgx1 = ctll::fixed_string{ RGX1 };
static constexpr auto ctre_rgx2 = ctll::fixed_string{ RGX2 };

constexpr auto match_line(std::string_view sv) noexcept {
    return ctre::match<ctre_line_rgx>(sv);
}

constexpr auto search_rgx1(std::string_view sv) noexcept {
    return ctre::search<ctre_rgx1>(sv);
}

constexpr auto search_rgx2(std::string_view sv) noexcept {
    return ctre::search<ctre_rgx2>(sv);
}

int main() {
    string s = "aaa.b.ccccc.dddd a.b.c.d aaaa.bb.c.ddddd";

    ctre::regex_results mlp = match_line(s);
    ctre::regex_results<const char*, ctre::captured_content<1, void>, ctre::captured_content<2, void>, ctre::captured_content<3, void>, ctre::captured_content<4, void> > mts1;
    ctre::regex_results<const char*, ctre::captured_content<1, void>, ctre::captured_content<2, void> > mts2;

    string_view _tmp = mlp.get<1>().to_view();
    cout << "parsing fields: " << _tmp << endl;
    while ( _tmp.size() > 0 && (mts1 = search_rgx1(_tmp)).size() > 0) {
        cout << mts1.get<1>().to_view() << " -> " << mts1.get<2>().to_view() << " -> " << mts1.get<3>().to_view() << " -> " << mts1.get<4>().to_view() << endl;
        if (mts1.size() >= _tmp.size())
             break;
        _tmp = _tmp.substr(mts1.size());
    }

    _tmp = mlp.get<1>().to_view();
    cout << "parsing fields: " << _tmp << endl;
    while ( _tmp.size() > 0 && (mts2 = search_rgx2(_tmp)).size() > 0) {
        cout << mts2.get<1>().to_view() << " -> " << mts2.get<2>().to_view() << endl;
        if (mts2.size() >= _tmp.size())
             break;
        _tmp = _tmp.substr(mts2.size());
    }
}

示例中mts1、mts2的类型由对应正则表达式确定,请问能否通过缩写或C++技巧避免逐个指定ctre::captured_content<N, void>参数?

解决方案

方法1:全局/命名空间作用域定义类型别名

利用decltype推导search_rgx函数的返回值类型,在全局或命名空间作用域定义类型别名,随后在块作用域直接复用:

// 全局/命名空间作用域定义类型别名
using Mts1Type = decltype(search_rgx1(std::string_view{}));
using Mts2Type = decltype(search_rgx2(std::string_view{}));

int main() {
    string s = "aaa.b.ccccc.dddd a.b.c.d aaaa.bb.c.ddddd";

    ctre::regex_results mlp = match_line(s);
    Mts1Type mts1; // 直接使用别名,无需手动编写模板参数
    Mts2Type mts2;

    // 后续逻辑保持不变...
}

该方式完全满足要求:不使用auto声明变量,块作用域无模板定义,类型由编译时自动推导且与正则表达式捕获组数量匹配。

方法2:封装通用类型推导模板

如果需要适配更多正则表达式,可在全局/命名空间作用域定义通用模板,快速提取对应regex_results类型:

template <ctll::fixed_string Regex>
using RegexResultsType = decltype(ctre::search<Regex>(std::string_view{}));

// 使用时指定目标正则表达式即可
using Mts1Type = RegexResultsType<ctre_rgx1>;
using Mts2Type = RegexResultsType<ctre_rgx2>;

int main() {
    Mts1Type mts1;
    Mts2Type mts2;
    // ...
}

此方式扩展性更强,新增正则表达式时只需复用模板,无需重复编写decltype逻辑。

方法3:变量声明时直接用decltype初始化

若不想提前定义类型别名,可在变量声明时结合decltype和默认初始化,直接推导类型:

int main() {
    string s = "aaa.b.ccccc.dddd a.b.c.d aaaa.bb.c.ddddd";

    ctre::regex_results mlp = match_line(s);
    decltype(search_rgx1(std::string_view{})) mts1{};
    decltype(search_rgx2(std::string_view{})) mts2{};

    // 后续逻辑保持不变...
}

该方式无需额外全局类型定义,直接在变量声明阶段完成类型推导,同样满足不使用auto、块作用域无模板的要求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 20:18:34