Firstly, some standard's quoted passage
If a template specialization X is referenced in a context that depends on a template-parameter of some surrounding template Y, the given point of instantation depends on the point of instantation of Y.
If X is a function template specialization, the point of instantiation is that of Y.
If X is a class template specialization, the point of instantiation is immediately before the point of instantiation of Y.
Otherwise, the given point of instantiation is tied to the location of the namespace scope declaration/definition (D) which contains the statement referring to X.
If X is a function template specialization, the point of instantiation is immediately after D.
If X is a class template specialization, the point of instantiation is immediately before D.
Some code here
#include <iostream>
template<int N>
struct state {
friend auto call(state<N>);
};
template<int N>
struct add_state {
friend auto call(state<N>) {
return N;
}
};
template<typename T, int N>
T show() {
add_state<N> d;
return T{};
}
template<typename T,int N>
class data {
public:
T c = show<T,N>();
};
#1,#3,#2
int main() {
data<int, 0> t;
call(state<0>{});
}
So, according to the above rules, when instantiating class data<int, 0>, then the point of instantiation is at #1.
Then show<T,N> depends on template class data's template parameters. So the point of instantiation for show<int,0> is at #2.
Then add_state<N> depends on template function show's template parameters. So according to the rules, the point of instantiation for add_state<0> is at #3.
At #3 auto call(state<0>) has been defined, call(state<0>{}) should be linked but in the fact, the compiler reports errors as follows:
clang:
main.cpp:24:2: error: function 'call' with deduced return type cannot be used before it is defined
call(state<0>{});
^
main.cpp:4:14: note: 'call' declared here
friend auto call(state<N>);
^
1 error generated.
g++:
main.cpp: In function ‘int main()’:
main.cpp:24:17: error: use of ‘auto call(state<0>)’ before deduction of ‘auto’
call(state<0>{});
^
Why? Does my understand about the point of instantiation has some mistakes?
If not, why does the compiler report these errors?
According to [temp.inst]/2.1, when a class template is implicitly instantiated, only the declaration of friends are instantiated:
The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions, default arguments, or noexcept-specifiers of the class member functions, member classes, scoped member enumerations, static data members, member templates, and friends;
So at #3 auto call(state<N>) is only declared. Moreover, this declaration is not found by ordinary unqualified name look-up.
Nevertheless I do not think that it makes your code formaly ill-formed. Your code is so strange that it is possible that such a situation has never been thought about by standard commitee members or compiler implementers: usualy inline friend functions are defined in the class that makes the friend function visible through ADL (Argument Dependent Name Lookup). This is certainly also what excepects a compiler.
So at call(state<0>{}) inside main, the declaration of call is found by ADL inside the definition of state and the compiler just don't think about looking for a potential definition of this function in the somehow unrelated class add_state. So it fails to deduce auto.
I'm not too confident myself in this matter, but in hope that this might prove useful I put together another working example, other than the ones already suggested:
#include <iostream>
// forward declaration of the
// add_state template
template<int>
struct add_state;
template<int N>
struct state {
// Note: we generate the state here
// so that the compiler will see the
// definition of the call function
add_state<N> t;
friend auto call(state<N>);
};
template<int N>
struct add_state {
friend auto call(state<N>) {
return N;
}
};
int main() {
auto val = call(state<42>{});
std::cout << val << std::endl;
return 0;
}
I'm not sure if this will help. But I hope so, as I, too would be interested in a good explanation.
Your issue is here:
template<int N>
struct state {
friend auto call(state<N>);//<--no way of telling return type !
};
The compiler has absolutely no way of telling of what the call functions returns and has to give up.
The fix is obvious as well, just give it something to work with, eg.:
friend auto call(state<N>) {return N;}
If used int instead of auto got error:
main.cpp:15: undefined reference to `call(state<0>)'
collect2.exe: error: ld returned 1 exit status
When added {return N;} to friend int call(state<N>), worked fine.
Then replaced back int to auto, it also works.
Related
[dcl.spec.auto]/14 states [emphasis mine]:
An explicit instantiation declaration does not cause the instantiation of an entity declared using a placeholder type, but it also does not prevent that entity from being instantiated as needed to determine its type. [ Example:
template <typename T> auto f(T t) { return t; }
extern template auto f(int); // does not instantiate f<int>
int (*p)(int) = f; // instantiates f<int> to determine its return type, but an explicit
// instantiation definition is still required somewhere in the program
— end example ]
and [temp.explicit]/11 states [emphasis mine]:
An entity that is the subject of an explicit instantiation declaration and that is also used in a way that would otherwise cause an implicit instantiation in the translation unit shall be the subject of an explicit instantiation definition somewhere in the program; otherwise the program is ill-formed, no diagnostic required.
Now, consider the following program:
template <class T>
struct Foo {
static const auto& foo() { static T t; return t; }
};
// explicit instantiation declarations
extern template const auto& Foo<void>::foo();
extern template const auto& Foo<int>::foo();
int main() {}
This is well-formed; [temp.explicit]/11 does not apply as neither member function of class template specialization entities Foo<void>::foo() nor Foo<int>::foo() are used in a way that would otherwise cause an implicit instantiation, as per [dcl.spec.auto]/14(1).
Now, consider if we defined a friend function at its friend declaration in the class template Foo:
template <class T>
struct Foo {
static const auto& foo() { static T t; return t; }
friend void bar() { }
};
void bar();
If any more than one specialization of Foo is instantiated in the same translation unit, [basic.def.odr]/1 will be violated:
No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template.
as the friend bar() would be re-defined(2) for each specialization that is instantiated.
According to the argument above, the explicit instantiation declarations of the two member function (of class template) specializations should not lead to any instantiation of the associated class template (as per [dcl.spec.auto]/14), meaning the following program should also arguably be well-formed:
template <class T>
struct Foo {
static const auto& foo() { static T t; return t; }
friend void bar() { }
};
void bar();
extern template const auto& Foo<void>::foo();
extern template const auto& Foo<int>::foo();
int main() {}
However, both Clang (10.0.0) and GCC (10.1.0) rejects the program (C++14, C++17, C++2a) with a "redefinition of void bar()” error:
Clang
error: redefinition of bar
note: in instantiation of template class Foo<int> requested here:
extern template const auto& Foo<int>::foo();
GCC
In instantiation of struct Foo<int>:
error: redefinition of void bar()
But I never requested (or, afaict, used these specializations in a way such that) the Foo<int> or Foo<void> specializations (are) to be instantiated.
Thus to the question:
Is the program (with the friend) above well-formed, or are the compilers correct to instantiate the class template specializations and subsequently reject the program?
(1) Note the the same question (and compiler behaviour) applies even if foo() is not declared using a placeholder type, but then we would not be able to fall back on the explicitness of [dcl.spec.auto]/14, but we may not need to.
(2) As friends defined at their friend declaration are inline, we may actually instantiate different specializations in different translation units and still respect ODR, but this is not relevant in this discussion.
The argument that the class template must be instantiated is that declaration matching may need to know things about the class that plainly require instantiation. Consider the simplified example
template<class T>
struct A {void f(T) {}};
extern template void A<int>::f(int);
To know whether the member function exists, we must instantiate the declaration in the class template, and we can’t do that in general without instantiating the whole class: the parameter type could depend on any other declarations in the class template, and we might need to consider multiple overloads or even do template argument deduction to decide which f is meant. One can argue that instantiation should happen only if one of these situations actually pertains, which strays into CWG2 territory (where instantiation is obviously impossible), but the idea is that instantiation is necessary in principle to decide about such questions because we simply don’t try examining the template itself first.
Consider the code:
class Test {
public:
template<int N> auto foo() {}
template<> auto foo<0>() { return 7; }
template<int N> void bar() {}
template<> int bar<0>() { return 7; }
};
I have tested the code with different compilers (through Compiler Explorer).
In case of Clang 7.0.0 foo compiles, while bar is giving an error:
:8:20: error: no function template matches function template
specialization 'bar'
template<> int bar<0>() { return 7; }
^
:7:26: note: candidate template ignored: could not match 'void
()' against 'int ()'
template<int N> void bar() {};
^
Visual C++ agrees (MSVC 19 2017 RTW):
(8): error C2912: explicit specialization 'int
Test::bar(void)' is not a specialization of a function template
gcc 8.2 does not compile any of the code (though the reason is probably a bug in C++17 support:
:5:14: error: explicit specialization in non-namespace scope
'class Test'
template<> auto foo<0>() { return 7; };
^
:5:28: error: template-id 'foo<0>' in declaration of primary
template
template<> auto foo<0>() { return 7; };
^
:7:26: error: too many template-parameter-lists
template<int N> void bar() {};
^~~
:8:14: error: explicit specialization in non-namespace scope
'class Test'
template<> int bar<0>() { return 7; }
^
:8:20: error: expected ';' at end of member declaration
template<> int bar<0>() { return 7; }
^~~
;
:8:23: error: expected unqualified-id before '<' token
template<> int bar<0>() { return 7; }
^
What is the correct interpretation here? Can I have a different return type for different method specializations (and why only with auto, but not while specifying them explicitly)? With my limited understanding of auto and templates I would go with saying "no". I don't understand why would using auto instead of explicitly naming the return type allow to have different return type for different specializations.
However, those codes are simplified versions of the code that I have found elsewhere, so maybe my interpretation is incorrect - and in that case I would be grateful for the explanation why different return type is allowed when auto is used for specialization, while explicitly naming the type seems to be forbidden.
There are several different problems with the example code.
1) GCC fails to implement CWG 727 (required in C++17): https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85282 which causes error: explicit specialization in non-namespace scope 'class Test'
2) If we ignore that, the example code can be simplified to just
template<int N> auto foo() {}
template<> auto foo<0>() { return 7; }
template<int N> void bar() {}
template<> int bar<0>() { return 7; }
which still exhibits the same errors. Now all compilers agree on the output. They compile foos and error out on the bar specialization.
why different return type is allowed when auto is used for specialization
It is allowed by a standard to specialize functions with auto return type if the specializations also have auto placeholder
Redeclarations or specializations of a function or function template with a declared return type that uses a placeholder type shall also use that placeholder, not a deduced type
http://eel.is/c++draft/dcl.spec.auto#11
So by virtue of this specialization conforming to the standard (being similar to one of the given examples) and not being explicitly forbidden anywhere it's allowed.
As for the error with bar, the standard says that return type is a part of function template signature:
⟨function template⟩ name, parameter type list ([dcl.fct]), enclosing namespace (if any), return type, template-head, and trailing requires-clause ([dcl.decl]) (if any)
http://eel.is/c++draft/defns.signature.templ
As such, in compiler's eyes template<> int bar<0>() { return 7; } is a specialization of template<... N> int bar(); template (notice the return type). But it wasn't declared previously (specialization can't precede declaration) so compilation fails! If you add template<int N> int bar(); then it'll compile (but complain about call ambiguity if you try to call bar).
Basically, you can't change the function signature in a specialization, you can only specialize (duh) template parameters (which should also be exactly the same as in declaration, since it's also part of the signature).
Can I have a template specialization with explicitly declared return type different from the base template at all
As explained - you can't change the function template signature which means you can't change the return type. BUT, you can specialize the return type if it depends on a template parameter!
Consider
template<int N, typename R = void> R bar() {}
template<> int bar<0>() { return 7; }
// bar<0, int> is deduced, see: http://eel.is/c++draft/temp.expl.spec#10
This is allowed but it has a disadvantage of having to write bar<0, int> when you want to make a call to a specialization: https://godbolt.org/z/4lrL62
This can be worked around by making the type conditional in the original declaration: https://godbolt.org/z/i2aQ5Z
But it'll quickly become cumbersome to maintain once the number of specializations grows.
Another, perhaps a bit more maintainable option, would be to return something like ret_type<N>::type and specialize that along with bar. But it's still won't be as clean as with just using auto.
Sorry for how complicated the title of this question is; I tried to describe the minimal SSCCE I constructed for this problem.
I have the following code:
#include <iostream>
namespace fizz
{
template<typename... Ts>
class bar
{
public:
template<int I, typename... Us>
friend auto foo(const bar<Us...> &);
private:
int i = 123;
};
template<int I, typename... Ts>
auto foo(const bar<Ts...> & b)
{
return b.i;
}
}
int main()
{
std::cout << fizz::foo<1>(fizz::bar<int, float>{});
}
This code compiles with GCC 5.2 and doesn't with Clang 3.7:
main.cpp:19:18: error: 'i' is a private member of 'fizz::bar<int, float>'
return b.i;
^
main.cpp:25:24: note: in instantiation of function template specialization 'fizz::foo<1, int, float>' requested here
std::cout << fizz::foo<1>(fizz::bar<int, float>{});
^
main.cpp:13:13: note: declared private here
int i = 123;
^
However, if you change the code slightly (although in a way that is not exactly useful for me, since in the real code this would introduce tons of boilerplate):
#include <iostream>
namespace fizz
{
template<typename... Ts>
class bar
{
public:
template<int I, typename... Us>
friend int foo(const bar<Us...> &);
private:
int i = 123;
};
template<int I, typename... Ts>
int foo(const bar<Ts...> & b)
{
return b.i;
}
}
int main()
{
std::cout << fizz::foo<1>(fizz::bar<int, float>{});
}
it suddenly works with that Clang 3.7.
The difference is that in the version of the code that doesn't compile with Clang, the friend function template uses C++14 auto return type deduction, while the working one plainly says it returns int. The same problem also happens with other variants of auto return type deduction, like auto && or const auto &.
Which compiler is right? Please provide some standard quotes to support the answer, since it is quite possible that a bug will need to be filed for one (...hopefully not both) compilers... or a standard defect, if both are right (which wouldn't be the first time).
I believe it's a clang bug. I want to approach it from this direction. What wrinkles does the auto placeholder type add, as compared to having a specified return type? From [dcl.spec.auto]:
The placeholder type can appear with a function declarator in the decl-specifier-seq, type-specifier-seq, conversion-function-id, or trailing-return-type, in any context where such a declarator is valid. If the function declarator includes a trailing-return-type (8.3.5), that trailing-return-type specifies the declared return type
of the function. Otherwise, the function declarator shall declare a function. If the declared return type of
the function contains a placeholder type, the return type of the function is deduced from return statements
in the body of the function, if any.
auto can appear in foo's declaration and definition, and is valid.
If the type of an entity with an undeduced placeholder type is needed to determine the type of an expression,
the program is ill-formed. Once a return statement has been seen in a function, however, the return type
deduced from that statement can be used in the rest of the function, including in other return statements. [ Example:
auto n = n; // error, n’s type is unknown
auto f();
void g() { &f; } // error, f’s return type is unknown
auto sum(int i) {
if (i == 1)
return i; // sum’s return type is int
else
return sum(i-1)+i; // OK, sum’s return type has been deduced
}
—end example ]
The first time we need to use determine the type of an expression, the return type of the function will already have been deduced from the return in the definition of foo(), so this is still valid.
Redeclarations or specializations of a function or function template with a declared return type that uses a
placeholder type shall also use that placeholder, not a deduced type.
We're using auto in both places, so we don't violate this rule either.
In short, there are several things that differentiate a specific return type from an placeholder return type from a function declaration. But all the usages of auto in the example are correct, so the namespace-scope foo should be seen as a redeclaration and definition of the first-declared friend auto foo within class template bar. The fact that clang accepts the former as a redeclaration for return type int but not for auto, and there is no relevant different for auto, definitely suggests this is a bug.
Further, if you drop the int I template parameter so that you can call foo unqualified, clang will report the call as ambiguous:
std::cout << foo(fizz::bar<int, float>{});
main.cpp:26:18: error: call to 'foo' is ambiguous
std::cout << foo(fizz::bar<int, float>{});
^~~
main.cpp:10:21: note: candidate function [with Us = <int, float>]
friend auto foo(const bar<Us...> &);
^
main.cpp:17:10: note: candidate function [with Ts = <int, float>]
auto foo(const bar<Ts...>& b)
^
So we have two function templates named foo in the same namespace (since from [namespace.memdef] the friend declaration for foo will place it in the nearest enclosing namespace) that take the same arguments and have the same return type (auto)? That shouldn't be possible.
It appears that your first example should work. There is a statement in C++14 (7.1.6.4 p12):
Redeclarations or specializations of a function or function template with a declared return type that uses a
placeholder type shall also use that placeholder, not a deduced type. [ Example:
.
.
.
template <typename T> struct A {
friend T frf(T);
};
auto frf(int i) { return i; } // not a friend of A<int>
The reason for the example appears to be to explain that to make the declarations match (and cause the defined function to be a friend) the declaration of frf inside struct A would also need to use auto. This implies to me that having a friend declaration with an auto return type and later defining the friend function (and also using auto) is allowed. I can't find anything that would make this work differently for a member function template, like in your example.
I have never gotten a great explanation of how template argument deduction really works, so I'm not sure how to explain behavior I'm seeing in the following:
template<typename T>
struct Base
{
protected:
template<bool aBool = true>
static void Bar(int)
{
}
};
template<typename T>
class Derived : public Base<T>
{
public:
void Foo() { Base<T>::Bar<false>(5); }
};
int main()
{
Derived<int> v;
v.Foo();
return 0;
}
This code won't build, and gives the error:
main.cpp: In instantiation of 'void Derived<T>::Foo() [with T = int]':
main.cpp:25:8: required from here main.cpp:19:15: error: invalid
operands of types '<unresolved overloaded function type>' and 'bool'
to binary 'operator<'
If you change the 2 Base<T>s in Derived to Base<int>, it compiles. If you change the call to Bar() to Base<T>::template Bar<false>(5);, it also compiles.
The one-liner I saw as an explanation for this is that the compiler doesn't know that Bar is a template, presumably because it doesn't know what Base is until a specialization of Derived is declared. But once the compiler starts generating code for Foo(), Base<T> has already been defined, and the type of Bar can be determined. What is causing the compiler to assume the symbol Bar is not a template, and attempting to apply operator<() instead?
I assume it has to do with the rules of when templates are evaluated in the compilation process - I guess what I'm looking for is a good comprehensive explanation of this process, such that the next time I run into code like the below, I can deduce the answer without the help of the good people on stack overflow.
Note I'm compiling with g++ 4.7, with c++x11 support.
void Foo() { Base<T>::Bar<false>(5); }
In this context Base<T> is a dependent name. To access a member template of a dependent name you need to add the template keyword:
void Foo() { Base<T>::template Bar<false>(5); }
Otherwise Base<T>::Bar will be parsed as a non-template member and < as less-than.
As of why the template is required, the reason is two-phase lookup. The error is triggered during the first pass, before the type is substituted, so the compiler does not know what is the definition of Base<T>. Consider for example that you added an specialization of Bar for int that had a non-template Bar member (say for example an int member). Before substituting T into Foo, the compiler does not know if there is an specialization for the type.
This is the statement from ISO C++ Standard 14.6.4.1 Point of instantiation
For a function template specialization, a member function template
specialization, or a specialization for a member function or static
data member of a class template, if the specialization is implicitly
instantiated because it is referenced from within another template
specialization and the context from which it is referenced depends on a
template parameter, the point of instantiation of the specialization is
the point of instantiation of the enclosing specialization. Otherwise,
the point of instantiation for such a specialization immediately follows
the namespace scope declaration or definition that refers to the
specialization.
If a function template or member function of a class template is called in
a way which uses the definition of a default argument of that function
template or member function, the point of instantiation of the default
argument is the point of instantiation of the function template or member
function specialization.
For a class template specialization, a class member template specialization,
or a specialization for a class member of a class template, if the
specialization is implicitly instantiated because it is referenced from
within another template specialization, if the context from which the
specialization is referenced depends on a template parameter, and if the
specialization is not instantiated previous to the instantiation of the
enclosing template, the point of instantiation is immediately before the
point of instantiation of the enclosing template. Otherwise, the point of
instantiation for such a specialization immediately precedes the
namespace scope declaration or definition that refers to the specialization.
I am unable to write a programs for this whole section. I am trying to write a programs for this section from yesterday.
Can any one provide me a code for this sections to understand.
Please, normally ..I tried to ask a 1 or more points. In any section. But here iam unable to understand a single point in this section.
So, kindly can any one provide me a code(programs) for this sections to understand.
I find this quite mind-screwing, and the committee has more such fun. So I think it's likely I have some errors in the below. So please read it with care :)
Third paragraph
For a class template specialization, a class member template specialization, or a specialization for a class member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization, if the context from which the specialization is referenced depends on a template parameter, and if the specialization is not instantiated previous to the instantiation of the enclosing template, the point of instantiation is immediately before the point of instantiation of the enclosing template.
In other words, if a class template or a nested class of a class template is instantiated, and the context that causes that instantiation depends on a template parameter, the template/nested class is instantiated immediately before the point of instantiation of the template that refers to it.
The context in the other specialization can either depend on template parameters, which is the case for primary templates, partial specializations and members of a class template, or it does not depend on template parameters, which is the case for references from within explicit specializations.
Otherwise [i.e. the context is nondependent], the point of
instantiation for such a specialization immediately precedes the namespace scope declaration or definition that refers to the specialization.
This distinction is important. Consider what would happen if the point of instantiation for specializations from dependent contexts would preceede immediately to the namespace scope declaration or definition that refers to it
template<typename T, int N>
struct A {
typedef typename A<T, N-1>::type *type;
};
template<typename T>
struct A<T, 0> {
typedef T type;
};
typedef A<int, 2>::type ptr;
This template is supposed to add N pointer declarators. So A<int, 2> is int** for example.
The context around typedef A<int, 2>::type is non-dependent, so A<int, 2> is instantiated before the typedef declaration.
Within A<int, 2>, we have A<int, N-1>::type, which appears in a dependent context and which references A<int, 1>::type. So the Standard requires us to instantiate A<int, 1> at the same point we instantiated A<int, 2>.
If we would instantiate this immediately before the namespace scope declaration that referred to it (before the primary template definition), we would not notice the partial specialization A<T, 0> when processing `A<int, N-1>::type within A<int, 1> because we would instantiate A<int, 1> before that specialization.
Second paragraph
This is just so that names looked up in default arguments are consistent with names looked up in the rest of the function that they are used for (i.e their POI is the same as the POI of their function template / member function of class template).
First paragraph
This is basically the same as the third paragraph. However, function templates are instantiated after the entity that refer to them so that recursive uses are possible, like in the following example. In contrast, class templates are instantiated before the entity that refer to them because the entity required that class type to be complete. If the class type's POI would be after that entity, the class type would still be non-existent.
template<typename T>
void f(T);
template<typename T>
struct A {
void g() {
f(0);
}
void h() { /* do a dance */ }
};
template<typename T>
void f(T t) {
A<T> a;
a.h();
}
void g() {
A<int> a;
a.g();
}
If f would be instantiated before A<int>, then it could not access a.h() because at that point it did not exist yet. Therefor, function templates are instantiated after the entity that refer to them, and class templates are instantiated before the entity that refer to them.
Request some one to correct my understanding...
I think the code below illustrates what 1 and 2 mean (from what I have understood):
template<class T> void f1(T t){cout << 0;}
template<class T> void f2(T t, void (*p)(int) = f1){
(*p)(0);
}
void f(double d){cout << 1;}
template<class T> void g(T t){
f1(t); // this is the interesting call.
}
void f1(int t){cout << 2;}
int main(){
g(2);
f2(2);
} // POI for f1(t), Also POI for f2(2)
Consider the call g(2). At the POI, there are basically three overloads (viable) that are visible:
function template
f(int)
f(double).
The call however routs to 'f(int)' as this is the best match.
In the same way, the POI for 'f2(2)' is the closing brace of main. The default argument 'f1' is once again looked up from this POI and resolves to 'f1(int)' which is the best match of all the three overloads available.
Thanks #litb. Revised after #litb corrected my understanding:
double f1(double d){cout << 1; return 0.0;}
template<class T> void f2(T t1, T t2 = f1(T())){}
template<class T> void g(T t){
f1(t); // this is the interesting call.
}
struct A{
friend A f1(A const &){cout << 2; return A();}
};
int main(){
g(A()); // 'f1(t)' resolves to friend function declaration
f2(A()); // The call to 'f1' in default argument also resolves to friend
// function declaration
// This is because for non dependent names, only ADL is performed
// at POI which is at closing brace of main.
} // POI for f1(t), Also POI for f2(2) in that order
Remember that in both the above calls, there are two overloads that are candidates. The namspace function 'f1(double)' and the friend function 'f1' declaration (found due to ADL). Since this is the only viable function, the calls resolve to the friend declaration 'f1'.
I think Point 3 means this:
template<class A> struct T{
T(int x = 0){}
};
template<class A> struct U{
U():t(f(A())){}
T<A> t;
}; // POI of 'gt' instantiation
T<int> gt(f(2)); // At this point 'f' is not found, hence error
int f(int x){return x;}
int main(){
U<int> u;
} // There are 2 POIs here 'U<int>::T<int>' and 'U<int>' and in that order
// Therefore 'f' is visible from here.