Skip to content

Commit b885e2e

Browse files
committed
support SFINAE via template arguments
#feat
1 parent 5de708b commit b885e2e

File tree

5 files changed

+100
-78
lines changed

5 files changed

+100
-78
lines changed

src/lib/AST/ASTVisitor.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,55 @@ populate(
14611461
{
14621462
populate(TI.Requires, RC);
14631463
}
1464+
else
1465+
{
1466+
// If there's no requires clause, check if the template
1467+
// parameter types we extracted have constraints
1468+
for (auto it = TI.Params.begin(); it != TI.Params.end(); )
1469+
{
1470+
std::unique_ptr<TParam>& param = *it;
1471+
1472+
if (auto const* T = dynamic_cast<NonTypeTParam*>(param.get());
1473+
T &&
1474+
T->Type &&
1475+
!T->Type->Constraints.empty())
1476+
{
1477+
for (ExprInfo const& constraint: T->Type->Constraints)
1478+
{
1479+
if (!TI.Requires.Written.empty())
1480+
{
1481+
TI.Requires.Written += " && ";
1482+
}
1483+
TI.Requires.Written += constraint.Written;
1484+
}
1485+
it = TI.Params.erase(it);
1486+
continue;
1487+
}
1488+
1489+
if (param->Default &&
1490+
param->Default->isType())
1491+
{
1492+
if (auto const* T = dynamic_cast<TypeTArg*>(param->Default.get());
1493+
T &&
1494+
T->Type &&
1495+
!T->Type->Constraints.empty())
1496+
{
1497+
for (ExprInfo const& constraint: T->Type->Constraints)
1498+
{
1499+
if (!TI.Requires.Written.empty())
1500+
{
1501+
TI.Requires.Written += " && ";
1502+
}
1503+
TI.Requires.Written += constraint.Written;
1504+
}
1505+
it = TI.Params.erase(it);
1506+
continue;
1507+
}
1508+
}
1509+
1510+
++it;
1511+
}
1512+
}
14641513
}
14651514

14661515
void

test-files/golden-tests/metadata/sfinae.adoc

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
| <<A-09,`A`>>
2323
| The partial specialization of A is enabled via a template parameter
2424

25-
| <<A-02,`A&lt;T, void&gt;`>>
25+
| <<A-02,`A&lt;T&gt;`>>
2626
| Specialization for floating point types
2727

2828
| <<S-02,`S`>>
@@ -123,7 +123,7 @@ class A;
123123

124124

125125
[#A-02]
126-
== A&lt;T, void&gt;
126+
== A&lt;T&gt;
127127

128128

129129
Specialization for floating point types
@@ -136,7 +136,8 @@ Declared in `&lt;sfinae&period;cpp&gt;`
136136
[source,cpp,subs="verbatim,replacements,macros,-callouts"]
137137
----
138138
template&lt;class T&gt;
139-
class <<A-09,A>>&lt;T, void&gt;;
139+
requires std&colon;&colon;is&lowbar;integral&lowbar;v&lt;T&gt;
140+
class <<A-09,A>>&lt;T&gt;;
140141
----
141142

142143

@@ -157,7 +158,7 @@ Declared in `&lt;sfinae&period;cpp&gt;`
157158
----
158159
template&lt;
159160
class T,
160-
class = void&gt;
161+
class Enable = void&gt;
161162
struct S;
162163
----
163164

@@ -261,11 +262,10 @@ Declared in `&lt;sfinae&period;cpp&gt;`
261262

262263
[source,cpp,subs="verbatim,replacements,macros,-callouts"]
263264
----
264-
template&lt;
265-
class T,
266-
typename = void&gt;
265+
template&lt;class T&gt;
266+
requires std&colon;&colon;is&lowbar;integral&lowbar;v&lt;T&gt;
267267
void
268-
f10(T* t);
268+
f10(T value);
269269
----
270270

271271
=== Description
@@ -346,9 +346,8 @@ Declared in `&lt;sfinae&period;cpp&gt;`
346346

347347
[source,cpp,subs="verbatim,replacements,macros,-callouts"]
348348
----
349-
template&lt;
350-
class T,
351-
bool = true&gt;
349+
template&lt;class T&gt;
350+
requires std&colon;&colon;is&lowbar;integral&lowbar;v&lt;T&gt;
352351
T
353352
f5(T value);
354353
----
@@ -366,9 +365,8 @@ Declared in `&lt;sfinae&period;cpp&gt;`
366365

367366
[source,cpp,subs="verbatim,replacements,macros,-callouts"]
368367
----
369-
template&lt;
370-
class T,
371-
bool = true&gt;
368+
template&lt;class T&gt;
369+
requires std&colon;&colon;is&lowbar;integral&lowbar;v&lt;T&gt;
372370
T
373371
f6(T value);
374372
----
@@ -386,9 +384,8 @@ Declared in `&lt;sfinae&period;cpp&gt;`
386384

387385
[source,cpp,subs="verbatim,replacements,macros,-callouts"]
388386
----
389-
template&lt;
390-
class T,
391-
int = 0&gt;
387+
template&lt;class T&gt;
388+
requires std&colon;&colon;is&lowbar;integral&lowbar;v&lt;T&gt;
392389
void
393390
f7(T value);
394391
----
@@ -408,9 +405,8 @@ Declared in `&lt;sfinae&period;cpp&gt;`
408405
----
409406
template&lt;class T&gt;
410407
T
411-
f8(
412-
T value,
413-
void* = 0);
408+
f8(T value)
409+
requires std&colon;&colon;is&lowbar;integral&lowbar;v&lt;T&gt;;
414410
----
415411

416412
[#f9]
@@ -428,9 +424,8 @@ Declared in `&lt;sfinae&period;cpp&gt;`
428424
----
429425
template&lt;class T&gt;
430426
T
431-
f9(
432-
T value,
433-
void* = 0);
427+
f9(T value)
428+
requires std&colon;&colon;is&lowbar;integral&lowbar;v&lt;T&gt;;
434429
----
435430

436431

test-files/golden-tests/metadata/sfinae.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ T
3636
f6(T value);
3737

3838
/// Enabled via a non-type template parameter using int instead of bool
39-
template<class T, std::enable_if_t<T::value1, int> = 0>
39+
template<class T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
4040
void f7(T value);
4141

4242
/// Enabled via parameter without helper
@@ -62,7 +62,7 @@ f9(T value, std::enable_if_t<std::is_integral_v<T>>* = 0);
6262
/// arguments are not accounted for in function template equivalence).
6363
///
6464
template<class T, typename = std::enable_if_t<std::is_integral_v<T>>>
65-
void f10(T* t);
65+
void f10(T value);
6666

6767
/// The partial specialization of A is enabled via a template parameter
6868
template<class T, class Enable = void>
@@ -73,7 +73,7 @@ template<class T>
7373
class A<T, std::enable_if_t<std::is_integral_v<T>>> {};
7474

7575
/// SFINAE with std::void_t
76-
template <class T, class = void>
76+
template <class T, class Enable = void>
7777
struct S
7878
{
7979
void store(const void*) {}

test-files/golden-tests/metadata/sfinae.html

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ <h2>Types</h2>
3333
<td><a href="#A-09"><code>A</code></a> </td><td><span><span>The partial specialization of A is enabled via a template parameter</span></span>
3434

3535
</td></tr><tr>
36-
<td><a href="#A-02"><code>A&lt;T, void&gt;</code></a> </td><td><span><span>Specialization for floating point types</span></span>
36+
<td><a href="#A-02"><code>A&lt;T&gt;</code></a> </td><td><span><span>Specialization for floating point types</span></span>
3737

3838
</td></tr><tr>
3939
<td><a href="#S-02"><code>S</code></a> </td><td><span><span>SFINAE with std::void_t</span></span>
@@ -147,7 +147,7 @@ <h3>Synopsis</h3>
147147
</div>
148148
<div>
149149
<div>
150-
<h2 id="A-02">A&lt;T, void&gt;</h2>
150+
<h2 id="A-02">A&lt;T&gt;</h2>
151151
<div>
152152
<span><span>Specialization for floating point types</span></span>
153153

@@ -161,7 +161,8 @@ <h3>Synopsis</h3>
161161
<pre>
162162
<code class="source-code cpp">
163163
template&lt;class T&gt;
164-
class <a href="#A-09">A</a>&lt;T, void&gt;;
164+
requires std::is_integral_v&lt;T&gt;
165+
class <a href="#A-09">A</a>&lt;T&gt;;
165166
</code>
166167
</pre>
167168
</div>
@@ -185,7 +186,7 @@ <h3>Synopsis</h3>
185186
<code class="source-code cpp">
186187
template&lt;
187188
class T,
188-
class = void&gt;
189+
class Enable = void&gt;
189190
struct S;
190191
</code>
191192
</pre>
@@ -309,11 +310,10 @@ <h3>Synopsis</h3>
309310
Declared in <code>&lt;sfinae.cpp&gt;</code></div>
310311
<pre>
311312
<code class="source-code cpp">
312-
template&lt;
313-
class T,
314-
typename = void&gt;
313+
template&lt;class T&gt;
314+
requires std::is_integral_v&lt;T&gt;
315315
void
316-
f10(T* t);
316+
f10(T value);
317317
</code>
318318
</pre>
319319
</div>
@@ -407,9 +407,8 @@ <h3>Synopsis</h3>
407407
Declared in <code>&lt;sfinae.cpp&gt;</code></div>
408408
<pre>
409409
<code class="source-code cpp">
410-
template&lt;
411-
class T,
412-
bool = true&gt;
410+
template&lt;class T&gt;
411+
requires std::is_integral_v&lt;T&gt;
413412
T
414413
f5(T value);
415414
</code>
@@ -431,9 +430,8 @@ <h3>Synopsis</h3>
431430
Declared in <code>&lt;sfinae.cpp&gt;</code></div>
432431
<pre>
433432
<code class="source-code cpp">
434-
template&lt;
435-
class T,
436-
bool = true&gt;
433+
template&lt;class T&gt;
434+
requires std::is_integral_v&lt;T&gt;
437435
T
438436
f6(T value);
439437
</code>
@@ -455,9 +453,8 @@ <h3>Synopsis</h3>
455453
Declared in <code>&lt;sfinae.cpp&gt;</code></div>
456454
<pre>
457455
<code class="source-code cpp">
458-
template&lt;
459-
class T,
460-
int = 0&gt;
456+
template&lt;class T&gt;
457+
requires std::is_integral_v&lt;T&gt;
461458
void
462459
f7(T value);
463460
</code>
@@ -481,9 +478,8 @@ <h3>Synopsis</h3>
481478
<code class="source-code cpp">
482479
template&lt;class T&gt;
483480
T
484-
f8(
485-
T value,
486-
void* = 0);
481+
f8(T value)
482+
requires std::is_integral_v&lt;T&gt;;
487483
</code>
488484
</pre>
489485
</div>
@@ -505,9 +501,8 @@ <h3>Synopsis</h3>
505501
<code class="source-code cpp">
506502
template&lt;class T&gt;
507503
T
508-
f9(
509-
T value,
510-
void* = 0);
504+
f9(T value)
505+
requires std::is_integral_v&lt;T&gt;;
511506
</code>
512507
</pre>
513508
</div>

0 commit comments

Comments
 (0)