By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,831 Members | 1,024 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,831 IT Pros & Developers. It's quick & easy.

Overload resolution of function templates

P: n/a
I have problems understanding how overloading of function templates
works.

Consider first the following code without any function templates ...

int foo(const char *& c)
{
return 0;
}

int foo(const char *c)
{
return 1;
}

int main() {
const char * s = "Hi!";
return foo(s);
}

Overloading resolution of foo is ambiguous, as can be witness by e.g. g
++

Foo.cpp: In function 'int main()':
Foo.cpp:14: error: call of overloaded 'foo(const char*&)' is ambiguous
Foo.cpp:2: note: candidates are: int foo(const char*&)
Foo.cpp:7: note: int foo(const char*)

If I now use function templates for foo, foo_t, as follows

template<typename C>
int foo_t(C& c)
{
return 0;
}

template<typename C>
int foo_t(const C *c)
{
return 1;
}

int main() {
const char * s = "Hi!";
return foo_t(s);
}

some implementations I tested (g++, msvc) seem to find a best
candidate function for foo_i which I do not understand.

As I read 13.3.1 para 7 of the standard, I would expect an
implementation to first determine specializations for foo_t (here:
foo_t<const char *and foo_t<charresp.), and then proceed as above.
Hence, I'd also expect an ambiguity error here. Where is my
misunderstanding?

Cheers,

Matthias

Oct 3 '08 #1
Share this Question
Share on Google+
7 Replies


P: n/a
On Oct 3, 10:07 am, matthias.neuba...@gmail.com wrote:
I have problems understanding how overloading of function templates
works.

Consider first the following code without any function templates ...

int foo(const char *& c)
{
return 0;
}

int foo(const char *c)
{
return 1;
}

int main() {
const char * s = "Hi!";
return foo(s);
}

template<typename C>
int foo_t(C& c)
{
return 0;
}

template<typename C>
int foo_t(const C *c)
{
return 1;
}

int main() {
const char * s = "Hi!";
return foo_t(s);
}

some implementations I tested (g++, msvc) seem to find a best
candidate function for foo_i which I do not understand.

As I read 13.3.1 para 7 of the standard, I would expect an
implementation to first determine specializations for foo_t (here:
foo_t<const char *and foo_t<charresp.), and then proceed as above.
Hence, I'd also expect an ambiguity error here. Where is my
misunderstanding?
The specializations are determined but now your function arguments
have changed. The two methods become:

int foot_t(const char*&)
and
int foo_t(const char**)

So if you're passing in a const char* my expectation would be the
foo_t(const char*&) method is called
Oct 3 '08 #2

P: n/a
mojumbo wrote:
On Oct 3, 10:07 am, matthias.neuba...@gmail.com wrote:
>I have problems understanding how overloading of function templates
works.

Consider first the following code without any function templates ...

int foo(const char *& c)
{
return 0;
}

int foo(const char *c)
{
return 1;
}

int main() {
const char * s = "Hi!";
return foo(s);
}

template<typename C>
int foo_t(C& c)
{
return 0;
}

template<typename C>
int foo_t(const C *c)
{
return 1;
}

int main() {
const char * s = "Hi!";
return foo_t(s);
}

some implementations I tested (g++, msvc) seem to find a best
candidate function for foo_i which I do not understand.

As I read 13.3.1 para 7 of the standard, I would expect an
implementation to first determine specializations for foo_t (here:
foo_t<const char *and foo_t<charresp.), and then proceed as above.
Hence, I'd also expect an ambiguity error here. Where is my
misunderstanding?

The specializations are determined but now your function arguments
have changed. The two methods become:

int foot_t(const char*&)
and
int foo_t(const char**)
Why? foo_t(const char**) wouldn't fit, and it wouldn't even be a possible
template instance (what would the template argument C be?).
But foo_t(const char*) would fit (with C=char). And actually, my compiler is
choosing that one.

Oct 3 '08 #3

P: n/a
On Oct 3, 3:07 pm, matthias.neuba...@gmail.com wrote:
I have problems understanding how overloading of function templates
works.
[...]
As I read 13.3.1 para 7 of the standard, I would expect an
implementation to first determine specializations for foo_t (here:
foo_t<const char *and foo_t<charresp.), and then proceed as above.
Hence, I'd also expect an ambiguity error here. Where is my
misunderstanding?
When function templates are involved then selection is based on which
candidate is more specialized. See "13.3.3 Best Viable Function" and
"14.5.6.2 Partial ordering of function templates" (Draft C++ Standard,
N2723).

For example,

template <class Tvoid foo (T a); // #1
template <class Tvoid foo (T* a); // #2, more specialized
int* a; foo (a); // selects #2

Regards,
Vidar Hasfjord
Oct 3 '08 #4

P: n/a
On Oct 3, 5:50*pm, Vidar Hasfjord <vattilah-gro...@yahoo.co.ukwrote:
When function templates are involved then selection is based on which
candidate is more specialized. See "13.3.3 Best Viable Function" and
"14.5.6.2 Partial ordering of function templates" (Draft C++ Standard,
N2723).
Ok, now I see. [over.match.best] compares function template
specializations differently. That's the part I was missing. Thanks!

Oct 3 '08 #5

P: n/a
On Fri, 03 Oct 2008 16:07:46 +0200, <ma***************@gmail.comwrote:
I have problems understanding how overloading of function templates
works.
.... snip ...
If I now use function templates for foo, foo_t, as follows

template<typename C>
int foo_t(C& c)
{
return 0;
}

template<typename C>
int foo_t(const C *c)
{
return 1;
}

int main() {
const char * s = "Hi!";
return foo_t(s);
}

some implementations I tested (g++, msvc) seem to find a best
candidate function for foo_i which I do not understand.

As I read 13.3.1 para 7 of the standard, I would expect an
implementation to first determine specializations for foo_t (here:
foo_t<const char *and foo_t<charresp.), and then proceed as above.
Hence, I'd also expect an ambiguity error here. Where is my
misunderstanding?
The reason why there is no ambiguity, is because the two functions are
ordered by the partial ordering of functions. That is, the second template
is more specialized than the first. That is possible because, when
matching (const C*) against C&, the reference is stripped from C& (see
14.8.2.1/2). If you call foo_t(1) [eg. calling the C& version with an
rvalue], overload resolution succeeds, but the call fails.

Regards
Jiri Palecek
Oct 6 '08 #6

P: n/a
On Oct 3, 7:42 pm, Jiří Paleček <jpale...@web.dewrote:
On Fri, 03 Oct 2008 16:07:46 +0200, <matthias.neuba...@gmail.comwrote:
template<typename C>
int foo_t(C& c)
{
return 0;
}
template<typename C>
int foo_t(const C *c)
{
return 1;
}
int main() {
const char * s = "Hi!";
return foo_t(s);
}
The reason why there is no ambiguity, is because the two functions are
ordered by the partial ordering of functions. That is, the second template
is more specialized than the first. That is possible because, when
matching (const C*) against C&, the reference is stripped from C& (see
14.8.2.1/2). If you call foo_t(1) [eg. calling the C& version with an
rvalue], overload resolution succeeds, but the call fails.
ALright. I am still a little bit confused. As you say, when comparing
function templates ("14.5.5.2 partial ordering of function
templates"), we perform argument deduction. But 14.5.5.2p4 also
dictates

"The transformed template is at least as specialized as the other
if, and only if, the deduction succeeds
and the deduced parameter types are an exact match (so the
deduction does not rely on implicit conversions)."

What exactly does the term "exact match" mean in this context? Is this
specified somewhere else?

In my example above, as I understand it, the deduced parameter type
for (C&) is

const C*&

which is NOT an exact match to

const C*.

Instead, we MUST use an implicit conversion to strip away the
reference.

Or, does the term "exact match" mean here, we still compare the
deduced parameter type and the expected parameter type "inexactly" by
ignoring
some parts as specified in 14.8.2.1?

-Matthias
Oct 7 '08 #7

P: n/a
On 7 Okt, 12:45, matthias.neuba...@gmail.com wrote:
On Oct 3, 7:42 pm, Jiří Paleček <jpale...@web.dewrote:


On Fri, 03 Oct 2008 16:07:46 +0200, <matthias.neuba...@gmail.comwrote:
* template<typename C>
* int foo_t(C& c)
* {
* *return 0;
* }
* template<typename C>
* int foo_t(const C *c)
* {
* *return 1;
* }
* int main() {
* * const char * s = "Hi!";
* * return foo_t(s);
* }
The reason why there is no ambiguity, is because the two functions are
ordered by the partial ordering of functions. That is, the second template
is more specialized than the first. That is possible because, when
matching (const C*) against C&, the reference is stripped from C& (see
14.8.2.1/2). If you call foo_t(1) [eg. calling the C& version with an
rvalue], overload resolution succeeds, but the call fails.

ALright. I am still a little bit confused. As you say, when comparing
function templates ("14.5.5.2 partial ordering of function
templates"), we perform argument deduction. But 14.5.5.2p4 also
dictates

* "The transformed template is at least as specialized as the other
if, and only if, the deduction succeeds
* *and the deduced parameter types are an exact match (so the
deduction does not rely on implicit conversions)."

What exactly does the term "exact match" mean in this context? Is this
specified somewhere else?

In my example above, as I understand it, the deduced parameter type
for (C&) is

* *const C*&

which is NOT an exact match to

* *const C*.

Instead, we MUST use an implicit conversion to strip away the
reference.

Or, does the term "exact match" mean here, we still compare the
deduced parameter type and the expected parameter type "inexactly" by
ignoring
some parts as specified in 14.8.2.1?

-Matthias
Yes, there is a special case for reference binding, so that the
conversion from const C* to const C*& has "Exact Match" ranking.
Oct 7 '08 #8

This discussion thread is closed

Replies have been disabled for this discussion.