J
Johannes Schaub (litb)
The desired outcome of the following is that it works (latest draft, n3126)
template<typename T> void f() { }
template<typename T> void g(T) { }
int main() { g(&f<int>); }
But I see a problem with that: When is the "&f" inspected in the gist of
14.8.1/3? We can have several places where we could apply it:
- Before argument dependent lookup is done. This would possibly affect
result of argument dependent lookup, because it might add associated classes
(if the function type of the specialization contains those classes).
- Before template argument deduction for the set of template candidates
found.
- After template argument deduction for the set of candidate functions
during overload resolution.
The Standard seems to be quiet about this, but there is a rationale to
reject the first and second bullet and to thus make the code ill-formed.
13.4 lists as one of the contexts that can be used to resolve a function
against a target type "a parameter of a function". In both the first and
second bullet, if we prematurely resolve "f<int>" using the arguments
provided in the template argument list, we would take away the possibility
of deducing "&f" later on to a concrete parameter. So we have to wait until
we get a final function template specialization against whose parameter we
could match by 13.4 and apply 14.8.2.1/6 in between:
"If the argument is an overload set containing one or more function
templates, the parameter is treated as a non-deduced context."
The above program would be ill-formed then because "T" cannot be deduced.
But the intent by 14.8.1/3 (as shown by its example code) is that the code
*is* valid, and that "f<int>" is resolved prior to this step, yet I miss
normative wording for both the case of deduction and the case of argument
dependent lookup.
As an example for the deduction case that yiels different results, consider
this
template<typename T = long> void f(void(*)(T));
template<typename U> void g(U);
template<typename U> void g(long);
int main() {
// - if resolved prematurely, this yields T = int
// - if resolved later, this yields T = long
f(0L, &g<int>);
}
Is this a defect, or am I just bloody blind again? Thanks for all your
insights!
template<typename T> void f() { }
template<typename T> void g(T) { }
int main() { g(&f<int>); }
But I see a problem with that: When is the "&f" inspected in the gist of
14.8.1/3? We can have several places where we could apply it:
- Before argument dependent lookup is done. This would possibly affect
result of argument dependent lookup, because it might add associated classes
(if the function type of the specialization contains those classes).
- Before template argument deduction for the set of template candidates
found.
- After template argument deduction for the set of candidate functions
during overload resolution.
The Standard seems to be quiet about this, but there is a rationale to
reject the first and second bullet and to thus make the code ill-formed.
13.4 lists as one of the contexts that can be used to resolve a function
against a target type "a parameter of a function". In both the first and
second bullet, if we prematurely resolve "f<int>" using the arguments
provided in the template argument list, we would take away the possibility
of deducing "&f" later on to a concrete parameter. So we have to wait until
we get a final function template specialization against whose parameter we
could match by 13.4 and apply 14.8.2.1/6 in between:
"If the argument is an overload set containing one or more function
templates, the parameter is treated as a non-deduced context."
The above program would be ill-formed then because "T" cannot be deduced.
But the intent by 14.8.1/3 (as shown by its example code) is that the code
*is* valid, and that "f<int>" is resolved prior to this step, yet I miss
normative wording for both the case of deduction and the case of argument
dependent lookup.
As an example for the deduction case that yiels different results, consider
this
template<typename T = long> void f(void(*)(T));
template<typename U> void g(U);
template<typename U> void g(long);
int main() {
// - if resolved prematurely, this yields T = int
// - if resolved later, this yields T = long
f(0L, &g<int>);
}
Is this a defect, or am I just bloody blind again? Thanks for all your
insights!