Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

template partial ordering rules underspecified #523

Open
brevzin opened this issue Jul 16, 2015 · 1 comment
Open

template partial ordering rules underspecified #523

brevzin opened this issue Jul 16, 2015 · 1 comment
Labels
cwg Issue must be reviewed by CWG.

Comments

@brevzin
Copy link
Contributor

brevzin commented Jul 16, 2015

There are several details in the template partial ordering rules that are underspecified. Both gcc and clang seem to agree on the algorithm for determining template ordering, but that algorithm doesn't actually appear in the standard. In no particular order:

Consistency of deduced values:

template <typename T> void foo(T, T); // (1)
template <typename T, typename U> void foo(T, U); // (2)

temp.deduct.type/2 makes it clear that there must be exactly one set of deduced values for the Ps. But there is no such statement in the partial ordering rule. The algorithm described only does pairwise P/A matching, so a synthesized call from (2) to (1) via foo(U{}, V{}) could succeed in deduction. Both gcc and clang agree that (1) is more specialized.

Type Synthesis Template Instantiation

template <typename T>
struct identity { using type = T; };

template<typename T> void bar(T, T ); // (1) 
template<typename T> void bar(T, typename identity<T>::type ); // (2)

Here, if synthesized for (2) Unique2 and typename identity<Unique2>::type == Unique2, then type deduction would succeed in both directions and the call bar(0,0) would be ambiguous. However, it seems that both compilers instead simply treat typename identity<Unique2>::type as Unique2_b, thus making template deduction from (2) to (1) fail (based on the implied missing Consistency rule).

Non-Deduced Context Omission

Same as previous example, but now define:

template <typename T> struct identity; template <> struct identity<int> { using type = int; };

With no template instantiation during synthesis and consistency, the (2) ==> (1) deduction fails. But if we consider the (1) ==> (2) call, we'd match T against Unique1 and then have the non-deduced context typename identity<Unique1>::type to match against Unique1, but that would be a substitution failure. It seems that the approach taken by gcc and clang (both of which prefer (1) here) is to ignore the non-deduced context argument, as long as that parameter type is deduced from a different template parameter type that did get matched.

The approaches that gcc/clang take make sense - but those rules should be spelled out in the standard.

@zygoloid zygoloid added the cwg Issue must be reviewed by CWG. label Jul 16, 2015
@t3nsor
Copy link
Contributor

t3nsor commented Dec 22, 2023

For the first issue, isn't it the case that [temp.deduct.partial]/8 tells us to use the [temp.deduct.type] rules to perform the deduction for one function template against the other transformed function type, so [temp.deduct.type]/2 would also apply in the partial ordering context?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cwg Issue must be reviewed by CWG.
Projects
None yet
Development

No branches or pull requests

3 participants