I was trying to understand how c++ template deals with name lookup and read this thread on stackoverflow:
Then I tried myself, as below:
#include<iostream>
using namespace std;
void bar (int){cout<<"int\n";}
template <typename T>
void foo (T const & t) {
bar (t);
}
template <typename T>
void bar (T){cout<<"t1\n";}
namespace NS {
struct A {};
}
int main () {
NS::A a;
foo (a);
}
It fails to compiler on either gcc/vc. gcc said:
<source>: In instantiation of 'void foo(const T&) [with T = NS::A]':
<source>:19:7: required from here
<source>:7:7: error: cannot convert 'const NS::A' to 'int'
7 | bar (t);
| ~~~~^~~
| |
| const NS::A
<source>:3:11: note: initializing argument 1 of 'void bar(int)'
3 | void bar (int){cout<<"int\n";}
| ^~~
Execution build compiler returned: 1
Seems that compiler finds bar(int)
and try to match foo()
, not considering template bar
.
But for my understanding: bar(t)
uses t
as dependent name, compiler shouldn't decide which bar()
to use at phase 1, and should postpone to phase 2 until template instantiation, right?
Then I moved the template bar
to the top of template foo
then it gets compiled and run:
void bar (int){cout<<"int\n";}
template <typename T>
void bar (T){cout<<"t1\n";} // moved to here
template <typename T>
void foo (T const & t) {
bar (t);
}
Or, If I put a none template bar
inside NS
, it also gets compiled:
void bar (int){cout<<"int\n";}
template <typename T>
void foo (T const & t) {
bar (t);
}
namespace NS {
struct A {};
void bar (A const &){} // add this one
}
My question: what's the core difference here, why the 1st code snippet fails, and the other 2 versions OK?