[clang] P3310 reverses partial ordering when template-template and template-id packs are empty
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
## Reproducer
```cpp
template
struct select;
template class C, class A, class... Rest>
struct select> { // candidate 1
static const int value = 1;
};
template class C, class A>
struct select> { // candidate 2
static const int value = 2;
};
template
struct unary;
static_assert(select>::value == 2, "");
```
```console
$ clang++ -std=c++11 -pedantic-errors -fsyntax-only repro.cpp
repro.cpp:18:15: error: static assertion failed due to requirement
'select>::value == 2'
repro.cpp:18:41: note: expression evaluates to '1 == 2'
```
## Expected result
Clang should select candidate 2. Its template-template parameter has the same
one-parameter template head as `unary`. Candidate 1 matches by leaving both
trailing packs empty.
Clang 19, Apple Clang 17, and GCC 15 select candidate 2. Clang 20 through
current trunk select candidate 1. Clang 20 selects candidate 2 with
`-fno-relaxed-template-template-args`.
## Regression
#124137 introduced the change while implementing P3310 and CWG2398. P3310's
invented default arguments take part in candidate-to-candidate partial ordering,
where Clang no longer has the actual `unary` template head. The variadic
candidate then wins.
A fix must preserve the `type_pack3` case in
`clang/test/SemaTemplate/cwg2398.cpp`. That case passes a template with a
defaulted second parameter and should select the variadic partial.
CWG1432 remains open, and Clang labels its implementation as provisional.
Please confirm whether the fixed partial should win when its template-template
parameter matches the actual template head and each competing mismatch comes
from a trailing template-template parameter pack.
## Related work
- #124137 implemented the P3310 and CWG2398 changes.
- #129436 fixed a code-completion crash in the CWG1432 tie-breaker.
- #177233 covers a separate function-template ordering case.
- [P3310R6](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3310r6.html)
- [CWG1432](https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1432)
Contributor guide
Research direction
Start by running the provided C++11 reproducer and reading clang/test/SemaTemplate/cwg2398.cpp, especially the type_pack3 case. Trace the P3310 and CWG2398 partial-ordering behavior introduced by #124137, then verify that the reproducer selects candidate 2 while type_pack3 still selects the variadic partial.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100