Home > Software design >  C - Declare variable with a variable template list without "auto"
C - Declare variable with a variable template list without "auto"

Time:09-05

I am using c 17 and I need to declare some variables that has the following type structure:

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<3, void>,
                    ctre::captured_content<4, void>,
                    ctre::captured_content<5, void>,
                    ctre::captured_content<6, void>,
                    ctre::captured_content<7, void>,
                    ctre::captured_content<8, void> > mts;

The number of ctre::captured_content in the template list is determined at compile-time. I was wondering if there exist a shorter way to declare them WITHOUT using auto. Also, I cannot use template due to this error: a template declaration cannot appear at block scope

The type I need is determined by this function:

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...>>();

UPDATE: A simple example:

#include <bits/stdc  .h>
#include "ctre.hpp" //  single-header of https://github.com/hanickadot/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());
    }
}

The types of mts1 and mts2 are determined based on the regex provided. Is it possible to avoid to specify all the ctre::captured_content<N, void> with an abbreviation or some c trick?

CodePudding user response:

It seems you want a typedef to shortened ctre::regex_results<const char*, ctre::captured_content<1, void>, .., ctre::captured_content<N, void>>

You might use decltype:

decltype(search_rgx1("")) mts1;
decltype(search_rgx2("")) mts2;

Alternatively, you might use (global scope):

template <typename Seq> struct regex_results_type_helper;

template <std::size_t... Is>
struct regex_results_type_helper<std::index_sequence<Is...>>
{
    using type = ctre::regex_results<const char*, ctre::captured_content<1   Is, void>...>;
}

template <std::size_t N>
using regex_results_type =
    typename regex_results_type_helper<std::make_index_sequence<N>>::type;

So you have, in your main

regex_results_type<4> mts1;
regex_results_type<2> mts2;

You can even have:

regex_results_type<group_count(ctre_rgx1)> mts1;
regex_results_type<group_count(ctre_rgx2)> mts2;

with appropriate constexpr function group_count

  • Related