Function overload resolution trouble
Over the weekend, I had specific problem with function overload resolution that I can't seem to solve. The code below is a distillation of the problem:
#include <iostream>
using namespace std;
template<typename T>
void f(const T& t)
{
cout << "In template function." << endl;
}
class C
{
public:
void f() { cout << "In class function." << endl; }
void g() { int i=0; f(i); }
void h() { int i=0; f<int>(i); }
void i() { extern void f(int); int i=0; f(i); }
};
int main()
{
cout << "Test" << endl;
C c;
c.i();
return 0;
}
1) C::g won't compile because the compiler won't try the template. It just complains that there is no C::f to match.
2) C::h won't compile for no reason that is obvious to me. The message is "expected primary-expression before 'int'"
3) C::i will compile, but (after commenting out g and h) it won't link to anything. I think I understand this: the extern is forcing the linker to look into another compilation unit, but any template definition would be in this compilation unit.
I would appreciate any clarification on the reasons for 1 and 2. Also, ultimately, can someone suggest a way to get this to work that doesn't involve creating another co开发者_Python百科mpilation unit?
Likely it is finding C::f
instead of global f
. Use ::f<int>(i)
.
Look here: http://ideone.com/zs9Ar
Output:
Test
In template function.
#include <iostream>
using namespace std;
template<typename T>
void f(const T& t)
{
cout << "In template function." << endl;
}
class C
{
public:
void f() { cout << "In class function." << endl; }
void g() { using ::f; int i=0; f(i); }
};
int main()
{
cout << "Test" << endl;
C c;
c.g();
return 0;
}
Names in a smaller scope hide names in an outer scope.
Use ::f
to indicate global namespace.
In i()
you declare a function called f
, but indeed there is no definition (it is not the same as the template), so you get a linker error.
C++ is somewhat "greedy" when trying to find functions. As soon as it finds a matching function name in the current scope (in this case, class C
) it stops and then tries to match the parameters. If the parameters don't match, it won't try additional scopes. I assume this was to keep compiler writers sane. That's why g
doesn't compile.
The same thing applies to h
. It sees a non-template function f
in the class scope and gets confused. It thinks you're trying to do a <
comparison against the function C::f
.
In both cases you can use ::f
to qualify the name to the global scope.
Functions with the same name will hide other functions of the same name when they have different scopes, even if they have different signatures.
Instead of using a template for the first f, you could just do f(int)
and the result would be the same for #1(the C::f() hides the ::f(int)).
One solution is to add "::" before the name to force the global namespace. Another solution would be to change the names.
精彩评论