@@ -2538,6 +2538,7 @@ struct declaration_node
2538
2538
2539
2539
std::vector<std::unique_ptr<id_expression_node>> metafunctions;
2540
2540
std::unique_ptr<parameter_declaration_list_node> template_parameters;
2541
+ std::unique_ptr<unqualified_id_node> specialization_template_arguments;
2541
2542
source_position requires_pos = {};
2542
2543
std::unique_ptr<logical_or_expression_node> requires_clause_expression;
2543
2544
@@ -2822,6 +2823,8 @@ struct declaration_node
2822
2823
2823
2824
auto is_function_expression () const -> bool
2824
2825
{ return is_function () && !identifier; }
2826
+ auto is_specialization () const -> bool
2827
+ { return specialization_template_arguments != nullptr ; }
2825
2828
2826
2829
auto is_polymorphic () const // has base types or virtual functions
2827
2830
-> bool
@@ -4745,6 +4748,11 @@ auto pretty_print_visualize(declaration_node const& n, int indent, bool include_
4745
4748
template_params += " " + pretty_print_visualize (*n.template_parameters , indent + 1 , true );
4746
4749
}
4747
4750
4751
+ auto specialization_args = std::string{};
4752
+ if (n.specialization_template_arguments ) {
4753
+ specialization_args += " " + pretty_print_visualize (*n.specialization_template_arguments , indent + 1 );
4754
+ }
4755
+
4748
4756
auto requires_clause = std::string{};
4749
4757
if (n.requires_clause_expression ) {
4750
4758
requires_clause += " requires (" + pretty_print_visualize (*n.requires_clause_expression , indent) + " )" ;
@@ -4829,7 +4837,8 @@ auto pretty_print_visualize(declaration_node const& n, int indent, bool include_
4829
4837
auto & type_id = std::get<declaration_node::an_object>(n.type );
4830
4838
assert (type_id);
4831
4839
ret += metafunctions
4832
- + template_params;
4840
+ + template_params
4841
+ + specialization_args;
4833
4842
if (!n.has_wildcard_type ()) {
4834
4843
ret += " " + pretty_print_visualize (*type_id, indent);
4835
4844
}
@@ -4841,6 +4850,7 @@ auto pretty_print_visualize(declaration_node const& n, int indent, bool include_
4841
4850
assert (t);
4842
4851
ret += metafunctions
4843
4852
+ template_params
4853
+ + specialization_args
4844
4854
+ " " + pretty_print_visualize (*t)
4845
4855
+ initializer;
4846
4856
}
@@ -4859,7 +4869,8 @@ auto pretty_print_visualize(declaration_node const& n, int indent, bool include_
4859
4869
object_type_id += " " + pretty_print_visualize (*a->type_id , indent);
4860
4870
}
4861
4871
4862
- ret += template_params;
4872
+ ret += template_params
4873
+ + specialization_args;
4863
4874
if (a->is_type_alias ()) {
4864
4875
auto & t = std::get<alias_node::a_type>(a->initializer );
4865
4876
ret += " type"
@@ -6160,6 +6171,7 @@ class parser
6160
6171
// G
6161
6172
// G template-argument-list:
6162
6173
// G template-argument-list ',' template-argument
6174
+ // G template-argument
6163
6175
// G
6164
6176
// G template-argument:
6165
6177
// G # note: < > << >> are not allowed in expressions until new ( is opened
@@ -7718,9 +7730,9 @@ class parser
7718
7730
// G unnamed-declaration:
7719
7731
// G ':' meta-functions-list? template-parameter-declaration-list? function-type requires-clause? '=' statement
7720
7732
// G ':' meta-functions-list? template-parameter-declaration-list? function-type statement
7721
- // G ':' meta-functions-list? template-parameter-declaration-list? type-id? requires-clause? '=' statement
7733
+ // G ':' meta-functions-list? template-parameter-declaration-list? template-specialization-argument-list? type-id? requires-clause? '=' statement
7722
7734
// G ':' meta-functions-list? template-parameter-declaration-list? type-id
7723
- // G ':' meta-functions-list? template-parameter-declaration-list? 'final'? 'type' requires-clause? '=' statement
7735
+ // G ':' meta-functions-list? template-parameter-declaration-list? template-specialization-argument-list? 'final'? 'type' requires-clause? '=' statement
7724
7736
// G ':' 'namespace' '=' statement
7725
7737
// G
7726
7738
// G meta-functions-list:
@@ -7732,7 +7744,10 @@ class parser
7732
7744
// G 'requires' logical-or-expression
7733
7745
// G
7734
7746
// G template-parameter-declaration-list
7735
- // G '<' parameter-declaration-seq '>'
7747
+ // G '<' parameter-declaration-seq? '>'
7748
+ // G
7749
+ // G template-specialization-argument-list:
7750
+ // G 'specialize' '<' template-argument-list '>'
7736
7751
// G
7737
7752
auto unnamed_declaration (
7738
7753
source_position start,
@@ -7877,6 +7892,21 @@ class parser
7877
7892
n->template_parameters = std::move (template_parameters);
7878
7893
}
7879
7894
7895
+ // Next is an optional template specialization argument list
7896
+ if (
7897
+ curr () == " specialize"
7898
+ && peek (1 )
7899
+ && peek (1 )->type () == lexeme::Less
7900
+ )
7901
+ {
7902
+ auto specialization_template_arguments = unqualified_id ();
7903
+ if (!specialization_template_arguments) {
7904
+ error (" invalid template specialization argument list" );
7905
+ return {};
7906
+ }
7907
+ n->specialization_template_arguments = std::move (specialization_template_arguments);
7908
+ }
7909
+
7880
7910
auto guard =
7881
7911
captures_allowed
7882
7912
? std::make_unique<capture_groups_stack_guard>(this , &n->captures )
@@ -8242,7 +8272,7 @@ class parser
8242
8272
// G alias:
8243
8273
// G ':' template-parameter-declaration-list? 'type' requires-clause? '==' type-id ';'
8244
8274
// G ':' 'namespace' '==' id-expression ';'
8245
- // G ':' template-parameter-declaration-list? type-id? requires-clause? '==' expression ';'
8275
+ // G ':' template-parameter-declaration-list? template-specialization-argument-list? type-id? requires-clause? '==' expression ';'
8246
8276
// G
8247
8277
// GT ':' function-type '==' expression ';'
8248
8278
// GT # See commit 63efa6ed21c4d4f4f136a7a73e9f6b2c110c81d7 comment
@@ -8271,12 +8301,34 @@ class parser
8271
8301
n->template_parameters = std::move (template_parameters);
8272
8302
}
8273
8303
8304
+ // Next is an optional template specialization argument list
8305
+ if (
8306
+ curr () == " specialize"
8307
+ && peek (1 )
8308
+ && peek (1 )->type () == lexeme::Less
8309
+ )
8310
+ {
8311
+ auto specialization_template_arguments = unqualified_id ();
8312
+ if (!specialization_template_arguments) {
8313
+ pos = start_pos; // backtrack
8314
+ return {};
8315
+ }
8316
+ n->specialization_template_arguments = std::move (specialization_template_arguments);
8317
+ }
8318
+
8274
8319
auto a = std::make_unique<alias_node>( &curr () );
8275
8320
8276
8321
// Next must be 'type', 'namespace', a type-id, or we're at the 'requires' or '=='
8277
8322
if (curr () == " type" )
8278
8323
{
8279
8324
next ();
8325
+ if (n->specialization_template_arguments ) {
8326
+ errors.emplace_back (
8327
+ curr ().position (),
8328
+ " a type alias cannot be specialized"
8329
+ );
8330
+ return {};
8331
+ }
8280
8332
}
8281
8333
else if (curr () == " namespace" )
8282
8334
{
@@ -8288,6 +8340,13 @@ class parser
8288
8340
);
8289
8341
return {};
8290
8342
}
8343
+ if (n->specialization_template_arguments ) {
8344
+ errors.emplace_back (
8345
+ curr ().position (),
8346
+ " a namespace alias cannot be specialized"
8347
+ );
8348
+ return {};
8349
+ }
8291
8350
}
8292
8351
else if (curr ().type () != lexeme::EqualComparison && curr () != " requires" )
8293
8352
{
0 commit comments