2012/7/1 Eric Niebler <
eric.n...@gmail.com>:
> Today I encountered a new and exciting strangeness in C++: argument
> dependent lookup can cause template instantiation *of template parameters*,
> which can lead to a hard error. Observe:
>
> template<typename T>
> struct wrap
> {
> typedef typename T::type type;
> };
>
> template<typename Fun>
> struct function
> {
> };
>
> template<typename F>
> void fun(F const &f)
> {}
>
> int main()
> {
> function<wrap<int>(int)> f;
> fun(f); // ERROR: ADL causes erroneous instantiation of wrap<int>
> }
>
> Since the call to fun is unqualified, it uses ADL, which searches the
> associated namespaces. It examines the type wrap<int> to find the associated
> namespaces, and in so doing it causes the template to be instantiated. But
> int is not a valid template argument to wrap, so the compilation fails. You
> can verify that it is in fact ADL that is causing the problem because when
> you qualify the call to fun, compilation succeeds. Wacky. I've tried this on
> 3 compilers (msvc 10, clang trunk, comeau online), and they all behave
> identically.
You can add gcc 4.8 to this list as well.
> My question is this: why does ADL need to instantiate wrap<int> to find its
> associated namespaces? IIUC, template parameters do indeed get used to
> populate the list of associated namespaces, but not the base classes of
> template parameters. So it seems to me that collecting the set of associated
> namespaces from template parameters does not requires any types found there
> to be complete. What have I missed?
My understanding is that they behave this way because for associated classes
the compiler has to respect visibility of potential friend functions
as described in
3.4.2 p4 b2.
- Daniel