@@ -2362,6 +2362,7 @@ struct declaration_node
2362
2362
2363
2363
std::vector<std::unique_ptr<id_expression_node>> meta_functions;
2364
2364
std::unique_ptr<parameter_declaration_list_node> template_parameters;
2365
+ std::unique_ptr<unqualified_id_node> specialization_template_arguments;
2365
2366
source_position requires_pos = {};
2366
2367
std::unique_ptr<logical_or_expression_node> requires_clause_expression;
2367
2368
@@ -4982,6 +4983,7 @@ class parser
4982
4983
// G
4983
4984
// G template-argument-list:
4984
4985
// G template-argument-list ',' template-argument
4986
+ // G template-argument
4985
4987
// G
4986
4988
// G template-argument:
4987
4989
// G # note: < > << >> are not allowed in expressions until new ( is opened
@@ -5031,20 +5033,20 @@ class parser
5031
5033
}
5032
5034
return expression (false ); // false == disallow unparenthesized relational comparisons in template args
5033
5035
}()
5034
- )
5036
+ )
5035
5037
{
5036
5038
term.arg = std::move (e);
5037
5039
}
5038
-
5040
+
5039
5041
// Else try parsing it as a type id
5040
5042
else if (auto i = type_id ()) {
5041
5043
term.arg = std::move (i);
5042
5044
}
5043
-
5045
+
5044
5046
else {
5045
5047
break ;
5046
5048
}
5047
-
5049
+
5048
5050
n->template_args .push_back ( std::move (term) );
5049
5051
}
5050
5052
// Use the lambda trick to jam in a "next" clause
@@ -6452,9 +6454,9 @@ class parser
6452
6454
6453
6455
// G unnamed-declaration:
6454
6456
// G ':' meta-functions-list? template-parameter-declaration-list? function-type requires-clause? '=' statement
6455
- // G ':' meta-functions-list? template-parameter-declaration-list? type-id? requires-clause? '=' statement
6457
+ // G ':' meta-functions-list? template-parameter-declaration-list? template-specialization-argument-list? type-id? requires-clause? '=' statement
6456
6458
// G ':' meta-functions-list? template-parameter-declaration-list? type-id
6457
- // G ':' meta-functions-list? template-parameter-declaration-list? 'final'? 'type' requires-clause? '=' statement
6459
+ // G ':' meta-functions-list? template-parameter-declaration-list? template-specialization-argument-list? 'final'? 'type' requires-clause? '=' statement
6458
6460
// G ':' 'namespace' '=' statement
6459
6461
// G
6460
6462
// G meta-functions-list:
@@ -6465,7 +6467,10 @@ class parser
6465
6467
// G 'requires' logical-or-expression
6466
6468
// G
6467
6469
// G template-parameter-declaration-list
6468
- // G '<' parameter-declaration-seq '>'
6470
+ // G '<' parameter-declaration-seq? '>'
6471
+ // G
6472
+ // G template-specialization-argument-list:
6473
+ // G 'type' '<' template-argument-list '>'
6469
6474
// G
6470
6475
auto unnamed_declaration (
6471
6476
source_position start,
@@ -6602,6 +6607,21 @@ class parser
6602
6607
n->template_parameters = std::move (template_parameters);
6603
6608
}
6604
6609
6610
+ // Next is an optional template specialization argument list
6611
+ if (
6612
+ curr () == " type"
6613
+ && peek (1 )
6614
+ && peek (1 )->type () == lexeme::Less
6615
+ )
6616
+ {
6617
+ auto specialization_template_arguments = unqualified_id ();
6618
+ if (!specialization_template_arguments) {
6619
+ error (" invalid template specialization argument list" );
6620
+ return {};
6621
+ }
6622
+ n->specialization_template_arguments = std::move (specialization_template_arguments);
6623
+ }
6624
+
6605
6625
auto guard =
6606
6626
captures_allowed
6607
6627
? std::make_unique<capture_groups_stack_guard>(this , &n->captures )
0 commit comments