class MyInt
{
int m_i;
public:
MyInt(int i)
: m_i{i}
{}
int get() const { return m_i; }
};
MyInt operator-(MyInt const& a)
{
return MyInt(-a.get());
}
booloperator > (MyInt const& l, MyInt const& r)
{
return l.get() > r.get();
}
using Int = MyInt;
template<typename T>
void ff(T i)
{
if (i > 0)
{
gg(-i);
}
}
void hh(Int x)
{
ff<Int>(x);
}
void gg(Int x)
{
ff<Int>(x);
}
The point of instantiation of ff<Int> is (I assume) on the first appearance of such template id (thus inside function hh). But at that point, there has not been even a declaration for gg(Int) so how can ff<Int> compile?
Does it have to do with the first phase recognizing there is a gg in scope and then applying this knowledge in the second phase?
ADL examines function declarations that are visible from the template definition context as well as in the template instantiation context [...] adding a new function declaration after template definition does not make it visible except via ADL
..although I suppose that's not quite precise enough to cover your case.. let's see if the standard is readable on this point.
Perhaps [temp.point]p8 is relevant:
for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation
. That gg is certainly visible from the end of the translation unit.
Or perhaps this is undefined due to [temp.dep.candidate]'s "If the call would find a better match had the lookup within the associated namespaces considered all the function declarations with external linkage introduced in those namespaces in all translation units[/quote]