value vs. const ref, char* vs char[4] - part 2

R

Rick

Is the following appropriate behavior? It certainly isn't what I
expected.


#include <iostream>

using namespace std;

template<typename T> bool fun(const T& value) {
cout << "In fun(const T&);" << endl;

}

template<typename T> bool fun(T value) {
cout << "In fun(T);" << endl;

}

int main(int argc, char** argv) {
fun(static_cast<const int&>(10) );

}

$ CC test.C
"test.C", line 14: Error: Overloading ambiguity between
"fun<int>(const int&)" and "fun<int>(int)".
1 Error(s) detected.
$
$
$ g++ test.C
test.C: In function `int main(int, char**)':
test.C:14: error: call of overloaded `fun(const int&)' is ambiguous
test.C:5: note: candidates are: bool fun(const T&) [with T = int]
test.C:9: note: bool fun(T) [with T = int]
$

I would have said that if I tell the compiler explicitly that I want a
const int&, there is no ambiguity. Something in the C++ standard
apparently says that this is correct behavior, but it seems wrong to
me.

Regards,

Abraham
 
B

Bo Persson

Rick said:
Is the following appropriate behavior? It certainly isn't what I
expected.


So your expectations are wrong. :)
#include <iostream>

using namespace std;

template<typename T> bool fun(const T& value) {
cout << "In fun(const T&);" << endl;

}

template<typename T> bool fun(T value) {
cout << "In fun(T);" << endl;

}

int main(int argc, char** argv) {
fun(static_cast<const int&>(10) );

}

$ CC test.C
"test.C", line 14: Error: Overloading ambiguity between
"fun<int>(const int&)" and "fun<int>(int)".
1 Error(s) detected.
$
$
$ g++ test.C
test.C: In function `int main(int, char**)':
test.C:14: error: call of overloaded `fun(const int&)' is ambiguous
test.C:5: note: candidates are: bool fun(const T&) [with T = int]
test.C:9: note: bool fun(T) [with T = int]
$

I would have said that if I tell the compiler explicitly that I
want a const int&, there is no ambiguity. Something in the C++
standard apparently says that this is correct behavior, but it
seems wrong to me.

Your problem is that there is not such thing as "a const int&",
because that is just a reference to an object that exists elsewhere.
It can't exist by itself.

Try this instead, assuming a class Person:

Person Robert; // A person called Robert

Person& Bob = Robert; // Another name for Robert

fun(Robert);
fun(Bob);

Do you want different overloads called depending on what name we use
for the same person? No!


Now this:

const number ten = 10;

const number& also_ten = ten;

fun(ten);
fun(also_ten);

Do you want different overloads called depending on what name we use
for the number 10? Not really!



Bo Persson
 
D

diligent.snail

Rick said:
Is the following appropriate behavior? It certainly isn't what I
expected.


#include <iostream>

using namespace std;

template<typename T> bool fun(const T& value) {
cout << "In fun(const T&);" << endl;

}

template<typename T> bool fun(T value) {
cout << "In fun(T);" << endl;

}

int main(int argc, char** argv) {
fun(static_cast<const int&>(10) );

}

$ CC test.C
"test.C", line 14: Error: Overloading ambiguity between
"fun<int>(const int&)" and "fun<int>(int)".
1 Error(s) detected.
$
$
$ g++ test.C
test.C: In function `int main(int, char**)':
test.C:14: error: call of overloaded `fun(const int&)' is ambiguous
test.C:5: note: candidates are: bool fun(const T&) [with T = int]
test.C:9: note: bool fun(T) [with T = int]
$

I would have said that if I tell the compiler explicitly that I want a
const int&, there is no ambiguity. Something in the C++ standard
apparently says that this is correct behavior, but it seems wrong to
me.

Regards,

Abraham

It seems to me too that the first template function is more
especialized, and should be prefered in overload resolution.

I tried the standard and did not manage to find explanation for the
compiler's behaviour.

Howvere, I tried your code with the Cameau compiler and it compiled
successfully:

http://www.comeaucomputing.com/tryitout/

So is it a compiler bug? Really do not know.

(by the way, which version of g++ are you using?)

Regards.
 
R

Rick

I tried to answer a little while ago and appear to have hit the wrong
button. Oh well.

Mr. Persson: Thanks for your explanation. It helps some. Do you
know where this behavior is described in the Standard?


Regards,

Abraham
 
B

Bo Persson

Rick said:
I tried to answer a little while ago and appear to have hit the
wrong button. Oh well.

Mr. Persson: Thanks for your explanation. It helps some. Do you
know where this behavior is described in the Standard?

I don't think it is described in one place, but as a combination of
several rules.

The minute details of overload resolution are really so complicated
that probably nobody really understands them fully. They are still
useful though, if you don't push it.

For function overloads, f(T) and f(const T&) are equally good. None of
them requires a conversion, or anything, for an object that is already
of type T. Like the compiler tells you, that means that it cannot
chose one of them as a better fit.

It also doesn't matter if you refer to Robert as Bob, he is still the
same object of the same type.



Bo Persson
 
A

Andrey Tarasevich

Rick said:
...
I would have said that if I tell the compiler explicitly that I want a
const int&, there is no ambiguity. Something in the C++ standard
apparently says that this is correct behavior, but it seems wrong to
me.
...

In general in C++ expressions that have reference types are always
immediately adjusted to the corresponding non-reference type for further
analysis (see 5/6). Also, the overload resolution specification in
13.3.3.2/3 clearly states that in this case overload is ambiguous (see
an example there).

(Although I don't know why Comeau accepts it. Maybe I'm missing
something related to templates. Without templates it fails in Comeau as
well.)

What you wrote in your code does not "tell the compiler explicitly" that
you want a "reference" version of the function. To "tell" something like
that you can force overload resolution by taking the function's address
first

(bool (*)(const int&)) fun(10);
 
A

Andrey Tarasevich

Andrey said:
What you wrote in your code does not "tell the compiler explicitly" that
you want a "reference" version of the function. To "tell" something like
that you can force overload resolution by taking the function's address
first

(bool (*)(const int&)) fun(10);

Oops... Should be

((bool (*)(const int&)) fun)(10);
 
R

Rick

Andrey,

Thanks very much for the standard references. I will peruse them
this evening.

Thanks also for the clarification about how to call a particular
overload explicitly. So to say that in English (I can be a little
laborious) it's: Cast the symbol "fun" to a pointer to a function
that takes a reference to a constant int and returns a bool, and call
the result with 10.


Regards,

Rick
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top