Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Identifying a single template specialization

Reply
Thread Tools

Identifying a single template specialization

 
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      09-04-2010
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!
 
Reply With Quote
 
 
 
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      09-04-2010
* Johannes Schaub (litb), on 04.09.2010 14:28:
> 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.


Don't know about the paragraph you refer to (I'd have to look it up), but the
way this works is that &f<int> is resolved as type void(*)(), then g<void(*)()>
is instantiated.



[snip rest]

Cheers & hth.,

- Alf

--
blog at <url: http://alfps.wordpress.com>
 
Reply With Quote
 
 
 
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      09-04-2010
Johannes Schaub (litb) wrote:

> [snipped]
> 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!


I guess I prematurely pressed the send button, haha. This call should read
"f(&g<int>)".

I think a further complication is the question whether partial ordering is
done on "g<int>" during processing of 14.8.1/3? If it's not done then this
would not be prematurely resolved because the requirement is that *a single*
function template specialization is found.

We can however use default arguments to make it valid for both cases to
yield a different result for each:

template<typename T = long> void f(void(*)(T));
template<typename U = int> void g(U);

int main() {
// - if resolved prematurely by 14.8.1/3, this yields T = int
// - if resolved later by 13.4, this yields T = long
f(&g<>);
}

The later resolving will see the target type as "void(*)(long)" and deduce
"g<>" to that, without needing to use the default argument. The premature
resolving will just resolve "g<>" using the default argument and deduce "T"
to int. Please forgive my premature acting.
 
Reply With Quote
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      09-04-2010
Alf P. Steinbach /Usenet wrote:

> * Johannes Schaub (litb), on 04.09.2010 14:28:
>> 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.

>
> Don't know about the paragraph you refer to (I'd have to look it up), but
> the way this works is that &f<int> is resolved as type void(*)(), then
> g<void(*)()> is instantiated.
>


Please see my follow-up post. My first post contained a flawed code example.
Even if partial ordering would be done on "&g<int>", in my post that would
give the same outcome for both cases because the second one is more
specialized and will thus give "void(*)(long)" as the function type.

My follow-up post contains an example which I believe is valid and its
outcome is unspecified.

You did snip my post and repeat the intended mechanism by the Standard. As
the DR that designed the wording of 14.8.1/3 and its example indicate, your
explanation is the intended mechanism. But I was wondering about the
normative wording. Is there any?
 
Reply With Quote
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      09-04-2010
Johannes Schaub (litb) wrote:

> Johannes Schaub (litb) wrote:
>> [snipped]
>> As an example for the deduction case that yiels different results,
>> consider this
>>

> [snipped]
> template<typename T = long> void f(void(*)(T));
> template<typename U = int> void g(U);
>
> int main() {
> // - if resolved prematurely by 14.8.1/3, this yields T = int
> // - if resolved later by 13.4, this yields T = long
> f(&g<>);
> }
>


Actually, I just tested clang and GCC, both coming up with different
results. Clang resolves it prematurely, and GCC resolves it later.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Full specialization of a member function template of a class template Dave C++ 4 06-04-2010 12:15 PM
template specialization overriding non-specialization? Joseph Turian C++ 2 04-16-2006 02:46 PM
Template specialization for templated and primitive type template parameters case2005 C++ 3 02-13-2005 06:53 PM
template specialization of a template class pit3k C++ 8 02-09-2005 02:39 AM
Specialization of a template within template David B. Held C++ 2 10-26-2003 11:59 AM



Advertisments