Author: Christof Meerwald (NVIDIA)
Document: P4004R0
Date: 2026-02-22
Target: EWG
Link: wg21.link/p4004r0
Christof Meerwald is asking EWG to revisit the resolution of CWG 1395, a core defect report from 2016 that changed how variadic and non-variadic function templates get partially ordered during overload resolution. The short version: the accepted resolution fundamentally changed how function parameter packs work during partial ordering, but a decade later only EDG actually implements it that way. GCC, Clang, and MSVC all do something different - and users expect the GCC/Clang/MSVC behavior.
The paper proposes two options. Option 1 reverts most of the CWG 1395 changes but keeps the trailing-pack tiebreaker in [temp.deduct.partial]/11, which would standardize what the three major compilers already do. Option 2 goes further and resolves additional ambiguity from CWG 1825. Full proposed wording is included for Option 1.
A paper to reconsider a resolution that reconsidered partial ordering. We have achieved template meta-standardization.
partial_ordering(partial_ordering(variadic_templates)). It compiles but instantiation has been pending since 2016.I have been writing C++ professionally for over a decade and I'm not sure I've ever consciously thought about partial ordering of variadic templates. This paper is for people operating three standard-ese layers above me.
The key sentence:
So GCC, Clang, and MSVC all agree on one behavior, the standard specifies something else, only EDG follows the standard, and EDG's users file bugs because they expect the GCC/Clang behavior. This is about as clear-cut a case for "standardize existing practice" as you're going to find.
Option 1 is conservative - revert the pack-expansion deduction changes but keep the trailing-pack tiebreaker in [temp.deduct.partial]/11. Straightforward fix.
Also worth noting - Option 2 (making the CWG 1825 example pick an overload instead of staying ambiguous) is left open without full wording. That feels like the more interesting design question. GCC and MSVC already pick
#2there, Clang says ambiguous. If we're standardizing existing practice, might as well go all the way.Hard to argue with that. When three implementations agree and the spec disagrees, the spec is the bug. The observation that the current wording doesn't even have normative backing for its own examples in [temp.deduct.partial]/8 is the cherry on top.
An entire paper about which of two function templates wins overload resolution, where even the committee's own defect resolution doesn't match what compilers actually do. This is the kind of thing that makes me sympathize with the "C++ is too complicated" crowd.
The partial ordering rules have an edge case that went unnoticed in practice for a decade. If anything that's evidence the system works fine for real code. This is cleanup, not a crisis.