@@ -130,6 +130,7 @@ struct id_expression_node;
130
130
struct declaration_node;
131
131
struct inspect_expression_node;
132
132
struct literal_node;
133
+ struct template_argument;
133
134
134
135
135
136
struct primary_expression_node
@@ -166,7 +167,7 @@ struct primary_expression_node
166
167
auto is_literal() const
167
168
-> bool;
168
169
169
- auto template_args_count () -> int ;
170
+ auto template_arguments () const -> std::vector<template_argument>& ;
170
171
171
172
auto get_token() const -> token const*;
172
173
@@ -1011,30 +1012,38 @@ auto prefix_expression_node::visit(auto& v, int depth)
1011
1012
struct type_id_node;
1012
1013
struct template_args_tag { };
1013
1014
1015
+ struct template_argument
1016
+ {
1017
+ enum active { empty=0, expression, type_id };
1018
+ source_position comma;
1019
+ std::variant<
1020
+ std::monostate,
1021
+ std::unique_ptr<expression_node>,
1022
+ std::unique_ptr<type_id_node>
1023
+ > arg;
1024
+
1025
+ auto to_string() const
1026
+ -> std::string;
1027
+
1028
+ // So that template_arguments() accessors can return a reference to an empty arg list
1029
+ static inline std::vector<template_argument> no_template_args;
1030
+ };
1031
+
1014
1032
1015
1033
struct unqualified_id_node
1016
1034
{
1017
1035
token const* identifier = {}; // required
1018
1036
1019
- enum active { empty=0 , expression, type_id };
1020
-
1021
1037
// These are used only if it's a template-id
1022
1038
source_position open_angle = {};
1023
1039
source_position close_angle = {};
1024
- struct term {
1025
- source_position comma;
1026
- std::variant<
1027
- std::monostate,
1028
- std::unique_ptr<expression_node>,
1029
- std::unique_ptr<type_id_node>
1030
- > arg;
1031
- };
1032
- std::vector<term> template_args;
1033
1040
1034
- auto template_args_count ()
1035
- -> int
1041
+ std::vector<template_argument> template_args;
1042
+
1043
+ auto template_arguments()
1044
+ -> std::vector<template_argument>&
1036
1045
{
1037
- return std::ssize ( template_args) ;
1046
+ return template_args;
1038
1047
}
1039
1048
1040
1049
auto get_token() const
@@ -1073,8 +1082,8 @@ struct unqualified_id_node
1073
1082
assert(template_args.empty()
1074
1083
|| template_args.front().comma == source_position{});
1075
1084
for (auto& a : template_args) {
1076
- try_visit<expression>(a.arg , v, depth+1 );
1077
- try_visit<type_id >(a.arg , v, depth+1 );
1085
+ try_visit<template_argument:: expression>(a.arg, v, depth+1);
1086
+ try_visit<template_argument:: type_id >(a.arg, v, depth+1);
1078
1087
}
1079
1088
v.end(template_args_tag{}, depth);
1080
1089
}
@@ -1094,6 +1103,12 @@ struct qualified_id_node
1094
1103
};
1095
1104
std::vector<term> ids;
1096
1105
1106
+ auto template_arguments() const
1107
+ -> std::vector<template_argument>&
1108
+ {
1109
+ return ids.back().id->template_arguments();
1110
+ }
1111
+
1097
1112
auto get_token() const
1098
1113
-> token const*
1099
1114
{
@@ -1207,14 +1222,14 @@ struct type_id_node
1207
1222
return tok && *tok == "concept";
1208
1223
}
1209
1224
1210
- auto template_args_count () const
1211
- -> int
1225
+ auto template_arguments () const
1226
+ -> std::vector<template_argument>&
1212
1227
{
1213
1228
if (id.index() == unqualified) {
1214
- return std::get<unqualified>(id)->template_args_count ();
1229
+ return std::get<unqualified>(id)->template_arguments ();
1215
1230
}
1216
1231
// else
1217
- return 0 ;
1232
+ return std::get<qualified>(id)->template_arguments() ;
1218
1233
}
1219
1234
1220
1235
auto to_string() const
@@ -1284,12 +1299,12 @@ auto unqualified_id_node::to_string() const
1284
1299
auto separator = std::string{"<"};
1285
1300
for (auto& t : template_args) {
1286
1301
ret += separator;
1287
- assert (t.arg .index () != empty);
1288
- if (t.arg .index () == expression) {
1302
+ assert(t.arg.index() != template_argument:: empty);
1303
+ if (t.arg.index() == template_argument:: expression) {
1289
1304
ret += "(expression)";
1290
1305
}
1291
- else if (t.arg .index () == type_id) {
1292
- ret += std::get<type_id>(t.arg )->to_string ();
1306
+ else if (t.arg.index() == template_argument:: type_id) {
1307
+ ret += std::get<template_argument:: type_id>(t.arg)->to_string();
1293
1308
}
1294
1309
separator = ",";
1295
1310
}
@@ -1298,6 +1313,23 @@ auto unqualified_id_node::to_string() const
1298
1313
return ret;
1299
1314
}
1300
1315
1316
+ auto template_argument::to_string() const
1317
+ -> std::string
1318
+ {
1319
+ switch (arg.index()) {
1320
+ break;case empty:
1321
+ return {};
1322
+ break;case expression:
1323
+ return std::get<expression>(arg)->to_string();
1324
+ break;case type_id:
1325
+ return std::get<type_id>(arg)->to_string();
1326
+ break;default:
1327
+ assert(!"ICE: invalid template_argument state");
1328
+ }
1329
+ // else
1330
+ return {};
1331
+ }
1332
+
1301
1333
1302
1334
struct is_as_expression_node
1303
1335
{
@@ -1434,14 +1466,14 @@ struct id_expression_node
1434
1466
std::unique_ptr<unqualified_id_node>
1435
1467
> id;
1436
1468
1437
- auto template_args_count ()
1438
- -> int
1469
+ auto template_arguments() const
1470
+ -> std::vector<template_argument>&
1439
1471
{
1440
1472
if (is_unqualified()) {
1441
- return std::get<unqualified>(id)->template_args_count ();
1473
+ return std::get<unqualified>(id)->template_arguments ();
1442
1474
}
1443
1475
// else
1444
- return 0 ;
1476
+ return std::get<qualified>(id)->template_arguments() ;
1445
1477
}
1446
1478
1447
1479
auto is_fold_expression() const
@@ -2466,7 +2498,7 @@ struct declaration_node
2466
2498
std::unique_ptr<alias_node>
2467
2499
> type;
2468
2500
2469
- std::vector<std::unique_ptr<id_expression_node>> meta_functions ;
2501
+ std::vector<std::unique_ptr<id_expression_node>> metafunctions ;
2470
2502
std::unique_ptr<parameter_declaration_list_node> template_parameters;
2471
2503
source_position requires_pos = {};
2472
2504
std::unique_ptr<logical_or_expression_node> requires_clause_expression;
@@ -3292,7 +3324,7 @@ struct declaration_node
3292
3324
try_visit<a_namespace>(type, v, depth+1);
3293
3325
try_visit<an_alias >(type, v, depth+1);
3294
3326
3295
- for (auto & m : meta_functions ) {
3327
+ for (auto& m : metafunctions ) {
3296
3328
assert(m);
3297
3329
m->visit(v, depth+1);
3298
3330
}
@@ -3608,14 +3640,14 @@ auto function_type_node::is_destructor() const
3608
3640
}
3609
3641
3610
3642
3611
- auto primary_expression_node::template_args_count ()
3612
- -> int
3643
+ auto primary_expression_node::template_arguments() const
3644
+ -> std::vector<template_argument>&
3613
3645
{
3614
3646
if (expr.index() == id_expression) {
3615
- return std::get<id_expression>(expr)->template_args_count ();
3647
+ return std::get<id_expression>(expr)->template_arguments ();
3616
3648
}
3617
3649
// else
3618
- return 0 ;
3650
+ return template_argument::no_template_args ;
3619
3651
}
3620
3652
3621
3653
@@ -4146,8 +4178,8 @@ auto pretty_print_visualize(unqualified_id_node const& n, int indent)
4146
4178
ret += ", ";
4147
4179
}
4148
4180
first = false;
4149
- ret += try_pretty_print_visualize<unqualified_id_node ::expression>(arg.arg , indent);
4150
- ret += try_pretty_print_visualize<unqualified_id_node ::type_id >(arg.arg , indent);
4181
+ ret += try_pretty_print_visualize<template_argument ::expression>(arg.arg, indent);
4182
+ ret += try_pretty_print_visualize<template_argument ::type_id >(arg.arg, indent);
4151
4183
}
4152
4184
ret += ">";
4153
4185
}
@@ -4570,7 +4602,7 @@ auto pretty_print_visualize(declaration_node const& n, int indent, bool include_
4570
4602
4571
4603
auto metafunctions = std::string{};
4572
4604
if (include_metafunctions_list) {
4573
- for (auto & meta : n.meta_functions ) {
4605
+ for (auto& meta : n.metafunctions ) {
4574
4606
metafunctions += " @" + pretty_print_visualize(*meta, indent);
4575
4607
}
4576
4608
}
@@ -6016,7 +6048,7 @@ class parser
6016
6048
n->open_angle = curr().position();
6017
6049
next();
6018
6050
6019
- auto term = unqualified_id_node::term {};
6051
+ auto term = template_argument {};
6020
6052
6021
6053
do {
6022
6054
// If it doesn't start with * or const (which can only be a type id),
@@ -7439,7 +7471,7 @@ class parser
7439
7471
}
7440
7472
7441
7473
7442
- auto apply_type_meta_functions ( declaration_node& decl )
7474
+ auto apply_type_metafunctions ( declaration_node& decl )
7443
7475
-> bool;
7444
7476
7445
7477
@@ -7589,7 +7621,7 @@ class parser
7589
7621
error("'@' must be followed by a a metafunction name", false);
7590
7622
return {};
7591
7623
}
7592
- n->meta_functions .push_back ( std::move (idx) );
7624
+ n->metafunctions .push_back( std::move(idx) );
7593
7625
}
7594
7626
7595
7627
// Next is an optional template parameter list
@@ -7647,9 +7679,9 @@ class parser
7647
7679
n->type = std::move(t);
7648
7680
assert (n->is_function());
7649
7681
7650
- if (!n->meta_functions .empty ()) {
7682
+ if (!n->metafunctions .empty()) {
7651
7683
errors.emplace_back(
7652
- n->meta_functions .front ()->position (),
7684
+ n->metafunctions .front()->position(),
7653
7685
"(temporary alpha limitation) metafunctions are currently not supported on functions, only on types"
7654
7686
);
7655
7687
return {};
@@ -7663,9 +7695,9 @@ class parser
7663
7695
assert (n->type.index() == declaration_node::a_namespace);
7664
7696
next();
7665
7697
7666
- if (!n->meta_functions .empty ()) {
7698
+ if (!n->metafunctions .empty()) {
7667
7699
errors.emplace_back(
7668
- n->meta_functions .front ()->position (),
7700
+ n->metafunctions .front()->position(),
7669
7701
"(temporary alpha limitation) metafunctions are currently not supported on namespaces, only on types"
7670
7702
);
7671
7703
return {};
@@ -7694,9 +7726,9 @@ class parser
7694
7726
n->type = std::move(t);
7695
7727
assert (n->is_object());
7696
7728
7697
- if (!n->meta_functions .empty ()) {
7729
+ if (!n->metafunctions .empty()) {
7698
7730
errors.emplace_back(
7699
- n->meta_functions .front ()->position (),
7731
+ n->metafunctions .front()->position(),
7700
7732
"(temporary alpha limitation) metafunctions are currently not supported on objects, only on types"
7701
7733
);
7702
7734
return {};
@@ -7840,7 +7872,7 @@ class parser
7840
7872
7841
7873
// If this is a type with metafunctions, apply those
7842
7874
if (n->is_type()) {
7843
- if (!apply_type_meta_functions (*n)) {
7875
+ if (!apply_type_metafunctions (*n)) {
7844
7876
error(
7845
7877
"error encountered while applying type metafunctions",
7846
7878
false, {}, true
0 commit comments