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