@@ -2557,6 +2557,7 @@ struct declaration_node
2557
2557
2558
2558
std::vector<std::unique_ptr<id_expression_node>> metafunctions;
2559
2559
std::unique_ptr<parameter_declaration_list_node> template_parameters;
2560
+ std::unique_ptr<unqualified_id_node> specialization_template_arguments;
2560
2561
source_position requires_pos = {};
2561
2562
std::unique_ptr<logical_or_expression_node> requires_clause_expression;
2562
2563
@@ -2841,6 +2842,8 @@ struct declaration_node
2841
2842
2842
2843
auto is_function_expression () const -> bool
2843
2844
{ return is_function () && !identifier; }
2845
+ auto is_specialization () const -> bool
2846
+ { return specialization_template_arguments != nullptr ; }
2844
2847
2845
2848
auto is_polymorphic () const // has base types or virtual functions
2846
2849
-> bool
@@ -4889,6 +4892,11 @@ auto pretty_print_visualize(declaration_node const& n, int indent, bool include_
4889
4892
template_params += " " + pretty_print_visualize (*n.template_parameters , indent + 1 , true );
4890
4893
}
4891
4894
4895
+ auto specialization_args = std::string{};
4896
+ if (n.specialization_template_arguments ) {
4897
+ specialization_args += " " + pretty_print_visualize (*n.specialization_template_arguments , indent + 1 );
4898
+ }
4899
+
4892
4900
auto requires_clause = std::string{};
4893
4901
if (n.requires_clause_expression ) {
4894
4902
requires_clause += " requires (" + pretty_print_visualize (*n.requires_clause_expression , indent) + " )" ;
@@ -4973,7 +4981,8 @@ auto pretty_print_visualize(declaration_node const& n, int indent, bool include_
4973
4981
auto & type_id = std::get<declaration_node::an_object>(n.type );
4974
4982
assert (type_id);
4975
4983
ret += metafunctions
4976
- + template_params;
4984
+ + template_params
4985
+ + specialization_args;
4977
4986
if (!n.has_wildcard_type ()) {
4978
4987
ret += " " + pretty_print_visualize (*type_id, indent);
4979
4988
}
@@ -4985,6 +4994,7 @@ auto pretty_print_visualize(declaration_node const& n, int indent, bool include_
4985
4994
assert (t);
4986
4995
ret += metafunctions
4987
4996
+ template_params
4997
+ + specialization_args
4988
4998
+ " " + pretty_print_visualize (*t)
4989
4999
+ initializer;
4990
5000
}
@@ -5003,7 +5013,8 @@ auto pretty_print_visualize(declaration_node const& n, int indent, bool include_
5003
5013
object_type_id += " " + pretty_print_visualize (*a->type_id , indent);
5004
5014
}
5005
5015
5006
- ret += template_params;
5016
+ ret += template_params
5017
+ + specialization_args;
5007
5018
if (a->is_type_alias ()) {
5008
5019
auto & t = std::get<alias_node::a_type>(a->initializer );
5009
5020
ret += " type"
@@ -6305,6 +6316,7 @@ class parser
6305
6316
// G
6306
6317
// G template-argument-list:
6307
6318
// G template-argument-list ',' template-argument
6319
+ // G template-argument
6308
6320
// G
6309
6321
// G template-argument:
6310
6322
// G # note: < > << >> are not allowed in expressions until new ( is opened
@@ -7868,9 +7880,9 @@ class parser
7868
7880
// G unnamed-declaration:
7869
7881
// G ':' meta-functions-list? template-parameter-declaration-list? function-type requires-clause? '=' statement
7870
7882
// G ':' meta-functions-list? template-parameter-declaration-list? function-type statement
7871
- // G ':' meta-functions-list? template-parameter-declaration-list? type-id? requires-clause? '=' statement
7883
+ // G ':' meta-functions-list? template-parameter-declaration-list? template-specialization-argument-list? type-id? requires-clause? '=' statement
7872
7884
// G ':' meta-functions-list? template-parameter-declaration-list? type-id
7873
- // G ':' meta-functions-list? template-parameter-declaration-list? 'final'? 'type' requires-clause? '=' statement
7885
+ // G ':' meta-functions-list? template-parameter-declaration-list? template-specialization-argument-list? 'final'? 'type' requires-clause? '=' statement
7874
7886
// G ':' 'namespace' '=' statement
7875
7887
// G
7876
7888
// G meta-functions-list:
@@ -7882,7 +7894,10 @@ class parser
7882
7894
// G 'requires' logical-or-expression
7883
7895
// G
7884
7896
// G template-parameter-declaration-list
7885
- // G '<' parameter-declaration-seq '>'
7897
+ // G '<' parameter-declaration-seq? '>'
7898
+ // G
7899
+ // G template-specialization-argument-list:
7900
+ // G 'specialize' '<' template-argument-list '>'
7886
7901
// G
7887
7902
auto unnamed_declaration (
7888
7903
source_position start,
@@ -8027,6 +8042,21 @@ class parser
8027
8042
n->template_parameters = std::move (template_parameters);
8028
8043
}
8029
8044
8045
+ // Next is an optional template specialization argument list
8046
+ if (
8047
+ curr () == " specialize"
8048
+ && peek (1 )
8049
+ && peek (1 )->type () == lexeme::Less
8050
+ )
8051
+ {
8052
+ auto specialization_template_arguments = unqualified_id ();
8053
+ if (!specialization_template_arguments) {
8054
+ error (" invalid template specialization argument list" );
8055
+ return {};
8056
+ }
8057
+ n->specialization_template_arguments = std::move (specialization_template_arguments);
8058
+ }
8059
+
8030
8060
auto guard =
8031
8061
captures_allowed
8032
8062
? std::make_unique<capture_groups_stack_guard>(this , &n->captures )
@@ -8392,7 +8422,7 @@ class parser
8392
8422
// G alias:
8393
8423
// G ':' template-parameter-declaration-list? 'type' requires-clause? '==' type-id ';'
8394
8424
// G ':' 'namespace' '==' id-expression ';'
8395
- // G ':' template-parameter-declaration-list? type-id? requires-clause? '==' expression ';'
8425
+ // G ':' template-parameter-declaration-list? template-specialization-argument-list? type-id? requires-clause? '==' expression ';'
8396
8426
// G
8397
8427
// GT ':' function-type '==' expression ';'
8398
8428
// GT # See commit 63efa6ed21c4d4f4f136a7a73e9f6b2c110c81d7 comment
@@ -8421,12 +8451,34 @@ class parser
8421
8451
n->template_parameters = std::move (template_parameters);
8422
8452
}
8423
8453
8454
+ // Next is an optional template specialization argument list
8455
+ if (
8456
+ curr () == " specialize"
8457
+ && peek (1 )
8458
+ && peek (1 )->type () == lexeme::Less
8459
+ )
8460
+ {
8461
+ auto specialization_template_arguments = unqualified_id ();
8462
+ if (!specialization_template_arguments) {
8463
+ pos = start_pos; // backtrack
8464
+ return {};
8465
+ }
8466
+ n->specialization_template_arguments = std::move (specialization_template_arguments);
8467
+ }
8468
+
8424
8469
auto a = std::make_unique<alias_node>( &curr () );
8425
8470
8426
8471
// Next must be 'type', 'namespace', a type-id, or we're at the 'requires' or '=='
8427
8472
if (curr () == " type" )
8428
8473
{
8429
8474
next ();
8475
+ if (n->specialization_template_arguments ) {
8476
+ errors.emplace_back (
8477
+ curr ().position (),
8478
+ " a type alias cannot be specialized"
8479
+ );
8480
+ return {};
8481
+ }
8430
8482
}
8431
8483
else if (curr () == " namespace" )
8432
8484
{
@@ -8438,6 +8490,13 @@ class parser
8438
8490
);
8439
8491
return {};
8440
8492
}
8493
+ if (n->specialization_template_arguments ) {
8494
+ errors.emplace_back (
8495
+ curr ().position (),
8496
+ " a namespace alias cannot be specialized"
8497
+ );
8498
+ return {};
8499
+ }
8441
8500
}
8442
8501
else if (curr ().type () != lexeme::EqualComparison && curr () != " requires" )
8443
8502
{
0 commit comments