I was having a problem in some production code that I minimized to the following test case:
template<typename T>
void intermediate(T t)
{
func(t); // line 4 ("func not declared in this scope")
}
namespace ns {
struct type {};
}
void func(ns::type const & p); // line 11 ("declared here, later")
void foo(ns::type exit_node)
{
intermediate(exit_node); // line 15 ("required from here")
}
GCC 4.5 compiles this fine. Both with and without -std=c++11
, 4.7 and 4.9 produce messages like:
test.cpp: In instantiation of ‘void intermediate(T) [with T = ns::type]’:
test.cpp:15:27: required from here
test.cpp:4:5: error: ‘func’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
test.cpp:11:6: note: ‘void func(const ns::type&)’ declared here, later in the translation unit
All of the following three things will cause the file to successfully compile:
- Move
func(ns::type)
into thens
namespace (allowing ADL to find it inns
) - Move
type
into the global namespace (allowing ADL to find it in::
) - Get rid of
intermediate
and callfunc
directly fromfoo
So... what is going on here? Is it legal for GCC to reject this program? Why is func
found by unqualified lookup in the third variant (call func
directly from foo
) but not found by unqualified lookup in the original variant at the point of instantiation?