Created attachment 28768 [details] Code reproducing bug Howdy, I think this is a bug in G++. I have a call to a template function filter(T) in a template context. filter() is further overloaded before the instantiation point. G++ 4.6.1 and 4.5.2 (both under MinGW, sorry, I don't have access to a more recent version) seems to resolve it at declaration point (see attachment for the exact code reproducing bug): namespace my { ... // A function template that by default behaves as identity template <typename P> typename std::remove_reference<P>::type filter(P&& p) throw() { return std::move(p); } ... } // of namespace my // Since this is unrestricted template, ADL won't work, so we have to stick // this overloaded operator building an expression template into the global scope template <typename P1> inline auto operator&(P1&& p1) throw() -> typename std::enable_if< my::is_mine<P1>::value, my::address<decltype(my::filter(std::forward<P1>(p1)))> >::type { // NOTE: call to filter depends on template argument, thus have to be // resolved at instantiation point. But it doesn't! return my::address<decltype(my::filter(std::forward<P1>(p1)))> (my::filter(std::forward<P1>(p1))); } // We now declare few more classes modeling our concept: var and ref namespace my { template <typename T> class var; template <typename T> class ref; ... // and specialize function filter on them template <typename T> inline ref<var<T>> filter( var<T>& t) throw() { return ref<var<T>>(t); } } // of namespace my int main() { my::var<int> h; auto&& a = &h; // Instantiate expression template via overloaded operator& std::cout << typeid(a).name() << std::endl; } GCC 4.6.1 output is: N2my7addressINS_3varIiEEEE which indicates that there is no ref<> applied to var<> in instantiation of address<>. Visual C++ 10 and 11 produce: struct my::address<struct my::ref<struct my::var<int> > > which have ref<> in between and is what I was actually expecting to have. If I move the definition of overloaded operator& after the second namespace my is closed, the ref<> does properly appear on top of the var<>. Can you please have a look at this? Thank you!
// NOTE: call to filter depends on template argument, thus have to be // resolved at instantiation point. // BUG: But it doesn't! I don't think this is true if it was using ADL, then it would be true but there is no ADL here so it only depends on the overloaded set that is done at the definition time.
Not sure I understand your comment - ADL with respect to what: my::filter or the ::operator&? Can you elaborate please?
(In reply to comment #2) > Not sure I understand your comment - ADL with respect to what: my::filter or > the ::operator&? Can you elaborate please? With respect to my::filter. Since it is a qualified name, the overloaded set is only considered at definition time rather than instantiation too.
Andrew is right, the standard says: In an expression of the form: postfix-expression ( expression-listopt) where the postfix-expression is an unqualified-id, the unqualified-id denotes a dependent name if [...] Since my::filter is not an unqualified-id it is not a dependent name, so the usual lookup rules apply and only names declared before the template definition can be found.