Skip to content

Commit cc36d55

Browse files
committed
feat: move template specializations and deduction guides off parent scope page
Class template specializations, function template specializations, and deduction guides used to share the enclosing scope's listing with their primary template. Users have repeatedly reported this as confusing: `vector` and `vector<int>` appearing side by side in the namespace index reads as if they were independent siblings, and a primary's variants were nowhere on its own page. Specializations now appear in a dedicated "Specializations" section on the primary's documentation page, and deduction guides in a "Deduction Guides" section on the deduced class's page. The parent scope's listing carries only the primary itself. An orphan specialization (one whose primary has been excluded from extraction) stays in the parent's listing so the index can still reach it. The relationship is stored in the corpus: each primary record or function template carries the IDs of its specializations (and, for class templates, of its deduction guides), and each specialization carries an `IsSpecialization` flag. The lists are populated by a finalizer pass and exposed via reflection, so the XML output gains matching `<specializations>`, `<deduction-guides>`, and `<is-specialization>` elements and the DOM/Handlebars layer renders the new sections through plain field access. Closes issue #1154.
1 parent 74bf1a3 commit cc36d55

110 files changed

Lines changed: 2966 additions & 492 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

include/mrdocs/Metadata/Symbol/Function.hpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <mrdocs/Metadata/Symbol/SymbolBase.hpp>
2323
#include <mrdocs/Metadata/Template.hpp>
2424
#include <mrdocs/Support/Describe.hpp>
25+
#include <mrdocs/Support/MapReflectedType.hpp>
2526
#include <string>
2627
#include <vector>
2728

@@ -137,6 +138,27 @@ struct FunctionSymbol final
137138
*/
138139
Optional<SymbolID> FunctionObjectImpl;
139140

141+
/** Whether this function is rendered on its primary's page.
142+
143+
Set by `SpecializationFinalizer` for function-template
144+
specializations whose primary is being extracted in
145+
@ref ExtractionMode::Regular. Such specializations are
146+
listed in the primary's "Specializations" section and
147+
suppressed from the parent scope's listing. Orphan
148+
specializations (primary excluded from extraction) keep
149+
the flag `false` so they remain reachable from the parent.
150+
*/
151+
bool IsSpecialization = false;
152+
153+
/** Specializations whose primary is this function.
154+
155+
Populated by `SpecializationFinalizer` with the IDs of
156+
function-template specializations referring to this
157+
function as their primary. Sorted by referent name
158+
then ID.
159+
*/
160+
std::vector<SymbolID> Specializations;
161+
140162
//--------------------------------------------
141163

142164
/** Construct a function symbol with its ID.
@@ -161,7 +183,8 @@ MRDOCS_DESCRIBE_STRUCT(
161183
IsNodiscard, IsExplicitObjectMemberFunction, Constexpr,
162184
OverloadedOperator, StorageClass, IsRecordMethod, IsVirtual,
163185
IsVirtualAsWritten, IsPure, IsConst, IsVolatile, IsFinal,
164-
RefQualifier, Explicit, Attributes, FunctionObjectImpl)
186+
RefQualifier, Explicit, Attributes, FunctionObjectImpl,
187+
IsSpecialization, Specializations)
165188
)
166189

167190
/** Map a vector of parameters to a @ref dom::Value object.

include/mrdocs/Metadata/Symbol/Record.hpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
8+
// Copyright (c) 2026 Gennaro Prota (gennaro.prota@gmail.com)
89
//
910
// Official repository: https://github.com/cppalliance/mrdocs
1011
//
@@ -74,6 +75,34 @@ struct RecordSymbol final
7475
*/
7576
std::vector<FriendInfo> Friends;
7677

78+
/** Whether this record is rendered on its primary's page.
79+
80+
Set by `SpecializationFinalizer` for class-template
81+
specializations whose primary is being extracted in
82+
@ref ExtractionMode::Regular. Such specializations are
83+
listed in the primary's "Specializations" section and
84+
suppressed from the parent scope's listing. Orphan
85+
specializations (primary excluded from extraction) keep
86+
the flag `false` so they remain reachable from the parent.
87+
*/
88+
bool IsSpecialization = false;
89+
90+
/** Specializations whose primary is this record.
91+
92+
Populated by `SpecializationFinalizer` with the IDs of
93+
class-template specializations referring to this record
94+
as their primary. Sorted by referent name then ID.
95+
*/
96+
std::vector<SymbolID> Specializations;
97+
98+
/** Deduction guides associated with this class template.
99+
100+
Populated by `SpecializationFinalizer` with the IDs of
101+
deduction guides that deduce this record. Sorted by
102+
referent name then ID.
103+
*/
104+
std::vector<SymbolID> DeductionGuides;
105+
77106
//--------------------------------------------
78107

79108
/** Create a record symbol bound to an ID.
@@ -93,7 +122,8 @@ MRDOCS_DESCRIBE_STRUCT(
93122
RecordSymbol,
94123
(SymbolCommonBase<SymbolKind::Record>),
95124
(KeyKind, Template, IsTypeDef, IsFinal, IsFinalDestructor,
96-
Bases, Derived, Interface, Friends)
125+
Bases, Derived, Interface, Friends,
126+
IsSpecialization, Specializations, DeductionGuides)
97127
)
98128

99129
/** Return the default accessibility for a record key kind.

mrdocs.rnc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,10 @@ grammar
370370
BaseInfo*,
371371
element derived { SymbolID }*,
372372
RecordInterface?,
373-
FriendInfo*
373+
FriendInfo*,
374+
element is-specialization { Bool }?,
375+
element specializations { SymbolID }*,
376+
element deduction-guides { SymbolID }*
374377
}
375378

376379
BaseInfo =
@@ -445,7 +448,9 @@ grammar
445448
element ref-qualifier { text }?,
446449
element explicit { text }?,
447450
element attributes { text }*,
448-
element function-object-impl { SymbolID }?
451+
element function-object-impl { SymbolID }?,
452+
element is-specialization { Bool }?,
453+
element specializations { SymbolID }*
449454
}
450455

451456
#---------------------------------------------

share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,16 @@
145145
{{/each}}
146146
|===
147147

148+
{{/if}}
149+
{{! Specializations of this primary template }}
150+
{{#if symbol.specializations}}
151+
{{>symbol/members-table members=symbol.specializations title="Specializations"}}
152+
153+
{{/if}}
154+
{{! Deduction guides for this class template }}
155+
{{#if symbol.deductionGuides}}
156+
{{>symbol/members-table members=symbol.deductionGuides title="Deduction Guides"}}
157+
148158
{{/if}}
149159
{{! Using symbols }}
150160
{{#if symbol.shadowDeclarations}}

share/mrdocs/addons/generator/common/partials/symbol/tranche.hbs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
88
Each value in the tranche is a list of symbols that belong to the tranche.
99
10+
Template specializations and deduction guides are filtered out: they are
11+
listed instead on the primary template's own page, via the dedicated
12+
"Specializations" / "Deduction Guides" sections.
13+
1014
Expected Context: {Tranche Object}
1115
1216
Example:
@@ -17,21 +21,20 @@
1721
{{#if is-namespace}}
1822
{{>symbol/members-table members=tranche.namespaces title="Namespaces"}}
1923
{{>symbol/members-table members=tranche.namespaceAliases title="Namespace Aliases"}}
20-
{{>symbol/members-table members=(concat tranche.records tranche.typedefs) title=(concat (select label (concat label " ") "") "Types")}}
24+
{{>symbol/members-table members=(concat (reject_by tranche.records "isSpecialization") tranche.typedefs) title=(concat (select label (concat label " ") "") "Types")}}
2125
{{>symbol/members-table members=tranche.enums title=(concat (select label (concat label " ") "") "Enums")}}
22-
{{>symbol/members-table members=tranche.functions title="Functions"}}
26+
{{>symbol/members-table members=(reject_by tranche.functions "isSpecialization") title="Functions"}}
2327
{{>symbol/members-table members=tranche.variables title="Variables"}}
2428
{{>symbol/members-table members=tranche.concepts title="Concepts"}}
25-
{{>symbol/members-table members=tranche.guides title=(concat (select label (concat label " ") "") "Deduction Guides")}}
2629
{{>symbol/members-table members=tranche.usings title=(concat (select label (concat label " ") "") "Using Declarations")}}
2730
{{else}}
2831
{{>symbol/members-table members=tranche.namespaceAliases title="Namespace Aliases"}}
29-
{{>symbol/members-table members=(concat tranche.records tranche.typedefs) title=(concat (select label (concat label " ") "") "Types")}}
32+
{{>symbol/members-table members=(concat (reject_by tranche.records "isSpecialization") tranche.typedefs) title=(concat (select label (concat label " ") "") "Types")}}
3033
{{>symbol/members-table members=tranche.enums title=(concat (select label (concat label " ") "") "Enums")}}
31-
{{>symbol/members-table members=tranche.functions title=(concat (select label (concat label " ") "") "Member Functions")}}
32-
{{>symbol/members-table members=tranche.staticFunctions title=(concat (select label (concat label " ") "") "Static Member Functions")}}
34+
{{>symbol/members-table members=(reject_by tranche.functions "isSpecialization") title=(concat (select label (concat label " ") "") "Member Functions")}}
35+
{{>symbol/members-table members=(reject_by tranche.staticFunctions "isSpecialization") title=(concat (select label (concat label " ") "") "Static Member Functions")}}
3336
{{>symbol/members-table members=tranche.variables title=(concat (select label (concat label " ") "") "Data Members")}}
3437
{{>symbol/members-table members=tranche.staticVariables title=(concat (select label (concat label " ") "") "Static Data Members")}}
3538
{{>symbol/members-table members=tranche.aliases title=(concat (select label (concat label " ") "") "Aliases")}}
3639
{{>symbol/members-table members=tranche.usings title=(concat (select label (concat label " ") "") "Using Declarations")}}
37-
{{/if}}
40+
{{/if}}

share/mrdocs/addons/generator/html/partials/symbol.html.hbs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,18 @@
192192
</table>
193193
</div>
194194
{{/if}}
195+
{{! Specializations of this primary template }}
196+
{{#if symbol.specializations}}
197+
<div>
198+
{{>symbol/members-table members=symbol.specializations title="Specializations"}}
199+
</div>
200+
{{/if}}
201+
{{! Deduction guides for this class template }}
202+
{{#if symbol.deductionGuides}}
203+
<div>
204+
{{>symbol/members-table members=symbol.deductionGuides title="Deduction Guides"}}
205+
</div>
206+
{{/if}}
195207
{{! Using symbols }}
196208
{{#if symbol.shadowDeclarations}}
197209
<div>

src/lib/CorpusImpl.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <lib/AST/MissingSymbolSink.hpp>
1717
#include <lib/AST/MrDocsFileSystem.hpp>
1818
#include <lib/Metadata/Finalizers/BaseMembersFinalizer.hpp>
19+
#include <lib/Metadata/Finalizers/SpecializationFinalizer.hpp>
1920
#include <lib/Metadata/Finalizers/DerivedFinalizer.hpp>
2021
#include <lib/Metadata/Finalizers/DocCommentFinalizer.hpp>
2122
#include <lib/Metadata/Finalizers/FunctionObjectFinalizer.hpp>
@@ -1078,6 +1079,14 @@ CorpusImpl::finalize()
10781079
finalizer.build();
10791080
}
10801081

1082+
// Populate primary -> specialization back-pointers
1083+
// and the deduction-guide lists on deduced records.
1084+
{
1085+
report::debug(" - Finalizing specializations");
1086+
SpecializationFinalizer finalizer(*this);
1087+
finalizer.build();
1088+
}
1089+
10811090
// Sort members: this runs unconditionally because
10821091
// the members of some symbol types are always sorted.
10831092
{

src/lib/CorpusImpl.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class CorpusImpl final : public Corpus
6464
friend class NamespacesFinalizer;
6565
friend class DerivedFinalizer;
6666
friend class FunctionObjectFinalizer;
67+
friend class SpecializationFinalizer;
6768

6869
public:
6970
/** Constructor.

0 commit comments

Comments
 (0)